There are currently five types of possible checks:
- joined a specific guild: requestGuildJoinCheck
- is the owner of a specific guild: requestGuildOwnerCheck
- is an admin of a specific guild: requestGuildAdminCheck
- satisfies requirements for a specific role: requestGuildRoleAccessCheck
- has a specific role: requestGuildRoleCheck
First, you'll need the GuildOracle abstract contract. Copy it to your project and leave it as it is.
You can Guild-gate any of the functions in your own contract in a few simple steps:
-
Import the GuildOracle contract:
import { GuildOracle } from "./GuildOracle.sol";
-
Make your contract inherit from the GuildOracle contract:
contract YourContract is GuildOracle /*, etc.*/ { /*...*/ }
-
Call the super contract's constructor. It will need 5 additional parameters, too.
constructor( /* your arguments */ uint256 guildId, address linkToken, address oracleAddress, bytes32 jobId, uint256 oracleFee ) GuildOracle(linkToken, oracleAddress, jobId, oracleFee) { /*...*/ }
For more info on what these are, refer to the docs.
For the LINK token's address on different chains check this page.
Guide to find a suitable oracle job here. Look for a GET > UINT256 job.Note: to get the id of your guild, one approach is to use this endpoint:
https://api.guild.xyz/v1/guild/[url-name-of-the-guild]
. Get the [url-name-of-the-guild] from the guild's link. Example: the url name ofhttps://guild.xyz/our-guild
is our-guild.
For some use cases you'll probably want to store the id of the role you want to gate with. To get the id of your preferred role, you can use the following endpoint:https://api.guild.xyz/v1/guild/[your-guild-id]
, where [your-guild-id] is the id of your guild. -
Split the logic of the function you want to gate:
- the user-facing function should contain only some checks, the request to the oracle and possibly emit an event. The oracle request should be a call to one of the requestGuild...Check functions (refer to Ways of Guild-gating).
Note: any parameters you wish to pass to the function that will be called by the oracle should be included in theargs
parameter in an abi encoded form, e.g.:abi.encode(var1, var2)
- the function called by the oracle with the response should only have two arguments:
bytes32 requestId
,uint256 access
. It also has to have the checkResponse modifier.
Note: the function's parameters cannot be extended, however, you can use the args parameter passed to the requestGuild...Check function in the previous step, you just have to abi decode them fromrequests[requestId].args
. Example with an address and a uint256 argument:(address var1, uint256 var2) = abi.decode(requests[requestId].args, (address, uint256));
- the user-facing function should contain only some checks, the request to the oracle and possibly emit an event. The oracle request should be a call to one of the requestGuild...Check functions (refer to Ways of Guild-gating).
Be sure to fund your contract with LINK tokens. The oracle will not respond if it's not getting paid.
Check out the already available Guild-gated example contracts in this project for further inspiration.
Remember when I wrote that you should copy the GuildOracle contract to your project and leave it as it is? Well, there's one case when you DO have to edit it. Some oracle jobs specify a times
parameter instead of multiply
. If you're using such a job, you should change the following line:
req.addInt("multiply", 1);
to this:
req.addInt("times", 1);