A vanilla Typescript dApp for claiming Ubiquity Rewards. It also includes tools for generating and invalidating permits and can be used to claim both ERC20 and ERC721 tokens.
- Install Foundry.
- Create a
.env
file in the project root with the following settings:
-
These are the suggested default test environment variables that allow for local setup using the supplied yarn commands. If you want to produce or invalidate real on-chain permits you must change the below values to reflect the real permit information such as address, chain ID, private key and so on.
# Common variables CHAIN_ID="31337" FRONTEND_URL="http://localhost:8080" UBIQUIBOT_PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" RPC_PROVIDER_URL="http://127.0.0.1:8545" PAYMENT_TOKEN_ADDRESS="0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d" # Storing tx data is not required to test locally although you do need to fill these with valid values # unless working on this feature specifically you won't need to build a supabase instance SUPABASE_URL=https://<yourSupabaseInstance>.supabase.co # used for storing permit tx data SUPABASE_ANON_KEY="...." # used for storing permit tx data # Variables depending on spender (bounty hunter) AMOUNT_IN_ETH="1" BENEFICIARY_ADDRESS="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" # Legacy env vars (only used when invalidating **REAL** permits via /scripts/solidity/getInvalidateNonceParams.ts) NONCE="0" NONCE_SIGNER_ADDRESS="0x"
- Set
.env
variables. - Run
yarn test:anvil
in terminal A andyarn test:fund
in terminal B. - In terminal B, run
yarn start
. - A permit URL for both ERC20 and ERC721 will be generated.
- Open the generated permit URL from the console.
- Connect your wallet (import anvil accounts [0] & [1] into your wallet).
- Depending on your connected account, either the claim or invalidate button will be visible.
- To test ERC721 permits, deploy the
nft-rewards
contract from the repository.
- Open your wallet provider and select
import wallet
orimport account
. - Obtain the private keys by running
anvil
or using the yarn command. - Copy and paste the private keys into your wallet provider.
- A local blockchain instance will be created for testing.
- The permit URL will be generated in the console. Ensure your console has enough space for the full URL.
- Imported anvil accounts [0] & [1] can claim and invalidate permits.
- Uses chain id
31337
and RPC providerhttp://localhost:8545
. - Claiming involves transferring tokens from the signer's account to the beneficiary's account.
- Signer must have signed a permit and have enough balance approved for the permit2 contract.
- Only the permit signer can invalidate it.
- Invalidating calls
invalidateUnorderedNonces
on thePermit2
smart contract.
- MetaMask is considered the default wallet provider.
- Ensure correct network selection in your wallet (
http://localhost:8545
with chain id31337
). - Use MetaMask Mobile Wallet Browser for mobile testing.
- Clear transaction history in MetaMask if transactions hang after restarting the Anvil instance.
- The test suite may show error toasts due to MetaMask spoofing.
- Ensure
.env
is correctly configured and wallet provider network is correct ifAllowance
orBalance
is0.00
. - Always start the Anvil instance before using
yarn start
as permit generation requires an on-chain call totoken.decimals()
.
- Admin sets
env.AMOUNT_IN_ETH
andenv.BENEFICIARY_ADDRESS
depending on a bounty hunter's reward and address - Admin generates an offline permit URL via
npx tsx generate-permit2-url.ts
. Permit URL example:
http://localhost:8080?claim=eyJwZXJtaXQiOnsicGVybWl0dGVkIjp7InRva2VuIjoiMHgxMWZFNEI2QUUxM2QyYTYwNTVDOEQ5Y0Y2NWM1NWJhYzMyQjVkODQ0IiwiYW1vdW50IjoiMTAwMDAwMDAwMDAwMDAwMDAwMCJ9LCJub25jZSI6IjQ0NTUxMjc4NTQwNTU0MzM1MDQ2NzU2NDQ3MzM2MjI1ODg5OTE4OTY5MTczODQwNTU0Nzk2NzQ3MzQzMzAwOTg0NzU4MDIyMzY1ODczIiwiZGVhZGxpbmUiOiIxMTU3OTIwODkyMzczMTYxOTU0MjM1NzA5ODUwMDg2ODc5MDc4NTMyNjk5ODQ2NjU2NDA1NjQwMzk0NTc1ODQwMDc5MTMxMjk2Mzk5MzUifSwidHJhbnNmZXJEZXRhaWxzIjp7InRvIjoiMHhjODZhMDU5NzgwMThlMDRkNmVGMmFhNzNFNjlhNzMzQzA2ZDFmODllIiwicmVxdWVzdGVkQW1vdW50IjoiMTAwMDAwMDAwMDAwMDAwMDAwMCJ9LCJvd25lciI6IjB4NTRmNGEzNjQyMkRjOTZkMDg0OTY3NWMxZjBkZDJCOTZEMjc1NThFMiIsInNpZ25hdHVyZSI6IjB4NWI0OTE5MjhmYzI4MzBlMjZiNTViMWUxOWQ3YzVhMmVjNGE2ZmRhYWI1OGFiYjgyOWMwNmYzYzlkNGE4YTc5YjAzYmE2NjlkMDM4YjFmYzg5NjgzYzMyYjBiYTA5MzU2MDRjMGU1MDNjYWE3ZmY2ZWM2MDg2ZWZlYjY2MTY5MjQxYyJ9
- Admin posts offline permit URL in issue comments (with the payment portal domain name)
- Bounty hunter opens permit URL, connects wallet and clicks a "withdraw" button to get a payment
This section describes how to invalidate the following permit (i.e. invalidate a permit2 nonce)
- Setup
.env
file with the required env variables:NONCE
(nonce number),NONCE_SIGNER_ADDRESS
(i.e. the bot's wallet) andRPC_PROVIDER_URL
. For this permit URL the.env
file will look like this:
NONCE="9867970486646789738815952475601005014850694197864057371518032581271992954680"
NONCE_SIGNER_ADDRESS="0xf87ca4583C792212e52720d127E7E0A38B818aD1"
RPC_PROVIDER_URL="https://rpc.ankr.com/gnosis"
- Run
yarn nonce:get-invalidate-params
. You will get this output:
== Logs ==
Is nonce used: false
--------------------
Params for nonce invalidation via invalidateUnorderedNonces()
wordPos: 38546759713464022417249814357816425839260524210406474107492314770593722479
mask: 72057594037927936
- Open https://gnosisscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3#writeContract and connect your wallet
- Call
invalidateUnorderedNonces()
with thewordPos
andmask
params you got on step 2
Notice that this examples uses gnosis chain for nonce invalidation. If you need to invalidate nonce on some other chain then:
- Set
RPC_PROVIDER_URL
on step 1 to the desired RPC chain provider - On step 3 open UI for the desired chain