diff --git a/src/classes/test/Contract/arcade/arcade.abi.json b/src/classes/test/Contract/arcade/arcade.abi.json new file mode 100644 index 0000000..0bd7117 --- /dev/null +++ b/src/classes/test/Contract/arcade/arcade.abi.json @@ -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" + } +] diff --git a/src/classes/test/Contract/arcade/arcade.unit.test.ts b/src/classes/test/Contract/arcade/arcade.unit.test.ts new file mode 100644 index 0000000..42ccdfa --- /dev/null +++ b/src/classes/test/Contract/arcade/arcade.unit.test.ts @@ -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); + }); +}); diff --git a/src/classes/test/Contract/foo.unit.test.ts b/src/classes/test/Contract/foo.unit.test.ts index 8519a44..846d464 100644 --- a/src/classes/test/Contract/foo.unit.test.ts +++ b/src/classes/test/Contract/foo.unit.test.ts @@ -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(); }); }); diff --git a/src/classes/utils/encode-decode-transaction.ts b/src/classes/utils/encode-decode-transaction.ts index b287d14..11ad5ff 100644 --- a/src/classes/utils/encode-decode-transaction.ts +++ b/src/classes/utils/encode-decode-transaction.ts @@ -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);