Skip to content

Commit

Permalink
Fix arcade dao function encoding (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
dawsbot authored Apr 30, 2024
1 parent a52cf67 commit e2c6ffb
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 11 deletions.
173 changes: 173 additions & 0 deletions src/classes/test/Contract/arcade/arcade.abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
[
{
"inputs": [
{ "internalType": "bytes32", "name": "_merkleRoot", "type": "bytes32" },
{
"internalType": "contract IERC20",
"name": "_token",
"type": "address"
},
{ "internalType": "uint256", "name": "_expiration", "type": "uint256" },
{
"internalType": "contract INFTBoostVault",
"name": "_votingVault",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{ "inputs": [], "name": "AA_AlreadyClaimed", "type": "error" },
{ "inputs": [], "name": "AA_ClaimingExpired", "type": "error" },
{ "inputs": [], "name": "AA_ClaimingNotExpired", "type": "error" },
{ "inputs": [], "name": "AA_NonParticipant", "type": "error" },
{ "inputs": [], "name": "AA_NotInitialized", "type": "error" },
{
"inputs": [
{ "internalType": "string", "name": "addressType", "type": "string" }
],
"name": "AA_ZeroAddress",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "merkleRoot",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "uint256",
"name": "expiration",
"type": "uint256"
}
],
"name": "SetMerkleRoot",
"type": "event"
},
{
"inputs": [{ "internalType": "address", "name": "who", "type": "address" }],
"name": "authorize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "", "type": "address" }],
"name": "authorized",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "address", "name": "delegate", "type": "address" },
{ "internalType": "uint128", "name": "totalGrant", "type": "uint128" },
{
"internalType": "bytes32[]",
"name": "merkleProof",
"type": "bytes32[]"
}
],
"name": "claimAndDelegate",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "internalType": "address", "name": "", "type": "address" },
{ "internalType": "bytes32", "name": "", "type": "bytes32" }
],
"name": "claimed",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "who", "type": "address" }],
"name": "deauthorize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "expiration",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "who", "type": "address" }],
"name": "isAuthorized",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "address", "name": "destination", "type": "address" }
],
"name": "reclaim",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "rewardsRoot",
"outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "bytes32", "name": "_merkleRoot", "type": "bytes32" },
{ "internalType": "uint256", "name": "_expiration", "type": "uint256" }
],
"name": "setMerkleRoot",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "who", "type": "address" }],
"name": "setOwner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "token",
"outputs": [
{ "internalType": "contract IERC20", "name": "", "type": "address" }
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "votingVault",
"outputs": [
{
"internalType": "contract INFTBoostVault",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]
21 changes: 21 additions & 0 deletions src/classes/test/Contract/arcade/arcade.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, expect, it } from 'vitest';
import type { JSONABIArgument } from '../../../../types/Contract.types';
import { encodeData } from '../../../utils/encode-decode-transaction';
import abi from './arcade.abi.json';

describe('arcade DAO contract', () => {
it('should encode [address, bytes32]', async () => {
const evmAddress = '0xE38a6F2045738Ea9F5Ad425E63537BA7679Eb82e';
const merkleRoot =
'0x9c76bb33425ea109e9bddd5ff9e97d10de0dc8de5d123a7c288f8387a4b2ba2d';
// this was captured by running it on the live network first
const mockEncoded =
'0x0f2d940b000000000000000000000000e38a6f2045738ea9f5ad425e63537ba7679eb82e9c76bb33425ea109e9bddd5ff9e97d10de0dc8de5d123a7c288f8387a4b2ba2d';
const args = [evmAddress, merkleRoot];
const jsonABIArgument = abi.find(
(abi) => abi.name === 'claimed',
) as JSONABIArgument;
const encoded = encodeData(jsonABIArgument, args);
expect(encoded).toBe(mockEncoded);
});
});
13 changes: 8 additions & 5 deletions src/classes/test/Contract/foo.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ describe('foo encode', () => {
(abi) => abi.name === 'baz',
) as JSONABIArgument;
const encoded = encodeData(jsonABIArgument, [69, true]);

expect(encoded).toBe(
'0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001',
);
});
it('encodes "bar" function', () => {
const args = [['0x010203', '0x040506']];
const functionName = 'bar';
const jsonABIArgument = fooABI.find(
(abi) => abi.name === 'bar',
(abi) => abi.name === functionName,
) as JSONABIArgument;
const encoded = encodeData(jsonABIArgument, ['abc', 'def']);
expect(encoded).toBe(
'0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000',
);

// const iface = new Interface(fooABI as any);
// const ethersEncoded = iface.encodeFunctionData(functionName, args);
expect(() => encodeData(jsonABIArgument, args)).toThrow();
});
});
13 changes: 7 additions & 6 deletions src/classes/utils/encode-decode-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,13 @@ export function encodeData(jsonABIArgument: JSONABIArgument, args: any[]) {
break;
default:
if (inputType.startsWith('bytes')) {
// encode each character to hex
const argEncoded = rawArg
.split('')
.map((character: string) => character.charCodeAt(0).toString(16))
.join('');
const paddedEncodedArg = argEncoded.padEnd(64, '0');
if (Array.isArray(arg)) {
throw new Error(
`essential-eth does not yet support "${inputType}[]" inputs. Make a PR today!"`,
);
}
const argEncoded = BigInt(arg).toString(16);
const paddedEncodedArg = argEncoded.padStart(64, '0');
return paddedEncodedArg;
} else if (inputType === 'uint256') {
const argEncoded = BigInt(arg).toString(16);
Expand Down

0 comments on commit e2c6ffb

Please sign in to comment.