diff --git a/contracts/SCERC721Derivative.sol b/contracts/SCERC721Derivative.sol index d945556..6112243 100644 --- a/contracts/SCERC721Derivative.sol +++ b/contracts/SCERC721Derivative.sol @@ -105,12 +105,12 @@ contract SCERC721Derivative is Derivative { } function _mint(address sender, BalanceProof memory proof) internal { - _checkNetwork(proof.input[42]); - _checkAttestor(proof.input[44]); - _checkThreshold(proof.input[45]); + _checkNetwork(proof.input[2]); + _checkAttestor(proof.input[5]); + _checkThreshold(proof.input[3]); _checkTokenAddress(proof); _checkProof(proof); - _mintWithNullifier(sender, proof.input[43]); + _mintWithNullifier(sender, proof.input[4]); } function _checkNetwork(uint256 _network) internal view { @@ -125,16 +125,13 @@ contract SCERC721Derivative is Derivative { bytes memory tokenBytes = bytes( Strings.toHexString(uint256(uint160(originalContract)), 20) ); - for (uint8 i = 0; i < 42; ) { - require( - uint8(proof.input[i]) == uint8(tokenBytes[i]), - "This ZK proof is not from the correct token contract" - ); - - unchecked { - ++i; - } - } + bytes memory contractBytes = bytes( + Strings.toHexString(uint256(uint160(proof.input[1])), 20) + ); + require( + keccak256(tokenBytes) == keccak256(contractBytes), + "This ZK proof is not from the correct token contract" + ); } function _checkProof(BalanceProof memory proof) internal view { diff --git a/contracts/SCERC721Ledger.sol b/contracts/SCERC721Ledger.sol index ecd1e8c..65068e9 100644 --- a/contracts/SCERC721Ledger.sol +++ b/contracts/SCERC721Ledger.sol @@ -60,6 +60,7 @@ pragma solidity ^0.8.16; import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; import "./base/Ledger.sol"; import "./SCERC721Derivative.sol"; @@ -97,8 +98,7 @@ contract SCERC721Ledger is Ledger { */ function mint(BalanceProof memory proof) external virtual { (string memory originalString, address original) = _extractAddress( - proof.input, - 0 + proof.input[1] ); // Check if derivative already exists if (!_checkDerivativeExistence(originalString)) { @@ -143,22 +143,13 @@ contract SCERC721Ledger is Ledger { /** * @dev Returns address from input */ - function _extractAddress(uint256[46] memory input, uint256 startIndex) + function _extractAddress(uint256 numAddress) internal pure returns (string memory, address) { - bytes memory result = new bytes(addressLength); - uint256 length = startIndex + addressLength; - for (uint256 i = startIndex; i < length; ) { - result[i] = bytes1(uint8(input[i])); - - unchecked { - ++i; - } - } - string memory addressString = string(result); - return (addressString, _toAddress(addressString)); + string memory addr = Strings.toHexString(uint256(uint160(numAddress)), 20); + return (addr, _toAddress(addr)); } // Credit to: https://github.com/provable-things/ethereum-api diff --git a/contracts/SCExternalERC721Ledger.sol b/contracts/SCExternalERC721Ledger.sol index f081ffc..373cb6e 100644 --- a/contracts/SCExternalERC721Ledger.sol +++ b/contracts/SCExternalERC721Ledger.sol @@ -105,8 +105,7 @@ contract SCExternalERC721Ledger is SCERC721Ledger { bytes32 vs ) external { (string memory originalString, address original) = _extractAddress( - proof.input, - 0 + proof.input[1] ); // Check if derivative already exists if (!_checkDerivativeExistence(originalString)) { diff --git a/contracts/SCFarcasterDerivative.sol b/contracts/SCFarcasterDerivative.sol index 58fa12a..61eb08a 100644 --- a/contracts/SCFarcasterDerivative.sol +++ b/contracts/SCFarcasterDerivative.sol @@ -109,7 +109,7 @@ contract SCFarcasterDerivative is Derivative { bytes memory farcasterBytes = bytes("farcaster"); for (uint8 i = 1; i < 10; ) { require( - uint8(proof.input[i]) == uint8(farcasterBytes[i]), + uint8(proof.input[i]) == uint8(farcasterBytes[i - 1]), "This ZK proof is not from the farcaster" ); diff --git a/contracts/interfaces/IBalanceCheckerVerifier.sol b/contracts/interfaces/IBalanceCheckerVerifier.sol index bd4270f..28d062f 100644 --- a/contracts/interfaces/IBalanceCheckerVerifier.sol +++ b/contracts/interfaces/IBalanceCheckerVerifier.sol @@ -64,6 +64,6 @@ interface IBalanceCheckerVerifier { uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, - uint256[46] memory input + uint256[6] memory input ) external view returns (bool r); } diff --git a/contracts/models/BalanceProof.sol b/contracts/models/BalanceProof.sol index 3b3ea51..389f1f0 100644 --- a/contracts/models/BalanceProof.sol +++ b/contracts/models/BalanceProof.sol @@ -63,5 +63,5 @@ struct BalanceProof { uint256[2] a; uint256[2][2] b; uint256[2] c; - uint256[46] input; + uint256[6] input; } diff --git a/test/ExternalSCERC721Ledger.ts b/test/ExternalSCERC721Ledger.ts index b418a78..9340fb2 100644 --- a/test/ExternalSCERC721Ledger.ts +++ b/test/ExternalSCERC721Ledger.ts @@ -15,9 +15,9 @@ import { expect } from 'chai' import { splitSignature } from 'ethers/lib/utils' const mintFunctionSignature = - 'mint((uint256[2],uint256[2][2],uint256[2],uint256[46]),bytes,bytes32,bytes32)' + 'mint((uint256[2],uint256[2][2],uint256[2],uint256[6]),bytes,bytes32,bytes32)' const mintFunctionSignatureWithOnlyProof = - 'mint((uint256[2],uint256[2][2],uint256[2],uint256[46]))' + 'mint((uint256[2],uint256[2][2],uint256[2],uint256[6]))' const invalidEcdsaWallet = new ethers.Wallet( '0x3931dc49c2615b436ed233b5f1bcba76cdc352f0318f8886d23f3e524e96a1be' diff --git a/test/SCERC721Ledger.ts b/test/SCERC721Ledger.ts index f506062..1beedb6 100644 --- a/test/SCERC721Ledger.ts +++ b/test/SCERC721Ledger.ts @@ -221,11 +221,7 @@ describe('SCERC721Ledger and SCERC721Derivative contracts tests', () => { await expect( this.scERC721Ledger.mint({ ...balanceInput, - input: [ - ...balanceInput.input.slice(0, -2), - invalidAttestorPublicKey, - balanceInput.input[balanceInput.input.length - 1], - ], + input: [...balanceInput.input.slice(0, 5), invalidAttestorPublicKey], }) ).to.be.revertedWith('This ZK proof is not from the correct attestor') }) diff --git a/test/SCFarcasterLedger.ts b/test/SCFarcasterLedger.ts index f543923..320fb1c 100644 --- a/test/SCFarcasterLedger.ts +++ b/test/SCFarcasterLedger.ts @@ -188,7 +188,7 @@ describe('SCFarcasterLedger and SCFarcasterDerivative contracts tests', () => { }) it('should not mint if the attestor is incorrect', async function () { const farcasterInput = getFakeFarcasterProof(123) - farcasterInput.input[10] = invalidAttestorPublicKey + farcasterInput.input[11] = invalidAttestorPublicKey await expect( this.scFarcasterLedger.mint(farcasterInput) ).to.be.revertedWith('This ZK proof is not from the correct attestor') @@ -196,11 +196,19 @@ describe('SCFarcasterLedger and SCFarcasterDerivative contracts tests', () => { it('should not mint if the "farcaster" word is incorrect', async function () { const farcasterInput = getFakeFarcasterProof(123) // Corrupt the message - farcasterInput.input[0] = 0 + farcasterInput.input[1] = 0 await expect( this.scFarcasterDerivative.mint(farcasterInput) ).to.be.revertedWith('This ZK proof is not from the farcaster') }) + it('should not mint if attestation type is invalid', async function () { + const farcasterInput = getFakeFarcasterProof(123) + // Corrupt the message + farcasterInput.input[0] = 1 + await expect( + this.scFarcasterDerivative.mint(farcasterInput) + ).to.be.revertedWith('Invalid attestation type') + }) it('should not mint if nullifier has already been used', async function () { await this.scFarcasterDerivative.mint(getFakeFarcasterProof(123)) await expect( diff --git a/test/utils.ts b/test/utils.ts index f90b7f1..273b98c 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -49,9 +49,9 @@ export async function getFakeBalanceVerifier(signer: SignerWithAddress) { type: 'uint256[2]', }, { - internalType: 'uint256[46]', + internalType: 'uint256[6]', name: 'input', - type: 'uint256[46]', + type: 'uint256[6]', }, ], name: 'verifyProof', @@ -130,7 +130,7 @@ export async function getFakeFarcasterVerifier(signer: SignerWithAddress) { { internalType: 'uint256[11]', name: 'input', - type: 'uint256[11]', + type: 'uint256[12]', }, ], name: 'verifyProof', @@ -227,19 +227,22 @@ function getFakeBalanceVerifierInput( contract: string, network: Network, nullifier: number, - threshold: number + threshold: number, + type = 0 ) { return [ - ...ethers.utils.toUtf8Bytes(contract.toLowerCase()), + type, + BigNumber.from(contract.toLowerCase()), network, + threshold, nullifier, attestorPublicKey, - threshold, ] } -function getFakeFarcasterVerifierInput(nullifier: number) { +function getFakeFarcasterVerifierInput(nullifier: number, type = 0) { return [ + type, ...ethers.utils.toUtf8Bytes('farcaster'), nullifier, attestorPublicKey,