diff --git a/.gas-snapshot b/.gas-snapshot index 4db2460b..908eab3b 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -59,8 +59,8 @@ BatchDistributorTest:testDistributeTokenMultipleAddressesSuccess() (gas: 764652) BatchDistributorTest:testDistributeTokenOneAddressSuccess() (gas: 727265) BatchDistributorTest:testDistributeTokenRevertWithInsufficientAllowance() (gas: 721109) BatchDistributorTest:testDistributeTokenRevertWithInsufficientBalance() (gas: 723840) -BatchDistributorTest:testFuzzDistributeEtherMultipleAddressesSuccess(((address,uint256)[]),uint256) (runs: 256, μ: 991885, ~: 925326) -BatchDistributorTest:testFuzzDistributeTokenMultipleAddressesSuccess(((address,uint256)[]),address,uint256) (runs: 256, μ: 1465306, ~: 1430877) +BatchDistributorTest:testFuzzDistributeEtherMultipleAddressesSuccess(((address,uint256)[]),uint256) (runs: 256, μ: 983113, ~: 924567) +BatchDistributorTest:testFuzzDistributeTokenMultipleAddressesSuccess(((address,uint256)[]),address,uint256) (runs: 256, μ: 1465307, ~: 1430877) Create2AddressTest:testComputeAddress() (gas: 702836) Create2AddressTest:testComputeAddressSelf() (gas: 711578) Create2AddressTest:testFuzzComputeAddress(bytes32,address) (runs: 256, μ: 703369, ~: 703369) @@ -88,11 +88,11 @@ CreateAddressTest:testComputeAddressSelfNonceUint8() (gas: 688618) CreateAddressTest:testComputeAddressSelfRevertTooHighNonce() (gas: 9122) CreateAddressTest:testFuzzComputeAddressNonce0x7f(uint64,address) (runs: 256, μ: 687670, ~: 687831) CreateAddressTest:testFuzzComputeAddressNonceUint16(uint64,address) (runs: 256, μ: 687167, ~: 687294) -CreateAddressTest:testFuzzComputeAddressNonceUint24(uint64,address) (runs: 256, μ: 687296, ~: 687398) +CreateAddressTest:testFuzzComputeAddressNonceUint24(uint64,address) (runs: 256, μ: 687297, ~: 687398) CreateAddressTest:testFuzzComputeAddressNonceUint32(uint64,address) (runs: 256, μ: 687294, ~: 687427) CreateAddressTest:testFuzzComputeAddressNonceUint40(uint64,address) (runs: 256, μ: 687401, ~: 687497) CreateAddressTest:testFuzzComputeAddressNonceUint48(uint64,address) (runs: 256, μ: 687399, ~: 687503) -CreateAddressTest:testFuzzComputeAddressNonceUint56(uint64,address) (runs: 256, μ: 687401, ~: 687510) +CreateAddressTest:testFuzzComputeAddressNonceUint56(uint64,address) (runs: 256, μ: 687403, ~: 687510) CreateAddressTest:testFuzzComputeAddressNonceUint64(uint64,address) (runs: 256, μ: 687431, ~: 687614) CreateAddressTest:testFuzzComputeAddressNonceUint8(uint64,address) (runs: 256, μ: 687169, ~: 687272) CreateAddressTest:testFuzzComputeAddressRevertTooHighNonce(uint256,address) (runs: 256, μ: 13321, ~: 13275) @@ -106,27 +106,31 @@ CreateAddressTest:testFuzzComputeAddressSelfNonceUint56(uint64) (runs: 256, μ: CreateAddressTest:testFuzzComputeAddressSelfNonceUint64(uint64) (runs: 256, μ: 693746, ~: 693897) CreateAddressTest:testFuzzComputeAddressSelfNonceUint8(uint64) (runs: 256, μ: 693257, ~: 693334) CreateAddressTest:testFuzzComputeAddressSelfRevertTooHighNonce(uint256) (runs: 256, μ: 13522, ~: 13480) -ECDSATest:testEthSignedMessageHash() (gas: 5847) -ECDSATest:testFuzzEthSignedMessageHash(string) (runs: 256, μ: 6441, ~: 6443) -ECDSATest:testFuzzRecoverWithInvalidSignature(bytes,string) (runs: 256, μ: 15174, ~: 15175) -ECDSATest:testFuzzRecoverWithTooLongSignature(bytes,string) (runs: 256, μ: 13115, ~: 13113) -ECDSATest:testFuzzRecoverWithValidSignature(string,string) (runs: 256, μ: 21703, ~: 21709) -ECDSATest:testFuzzRecoverWithWrongMessage(string,string,bytes32) (runs: 256, μ: 21714, ~: 21724) +ECDSATest:testEthSignedMessageHash() (gas: 5859) +ECDSATest:testFuzzEthSignedMessageHash(string) (runs: 256, μ: 6452, ~: 6455) +ECDSATest:testFuzzRecoverWithInvalidSignature(bytes,string) (runs: 256, μ: 15181, ~: 15182) +ECDSATest:testFuzzRecoverWithTooLongSignature(bytes,string) (runs: 256, μ: 13144, ~: 13142) +ECDSATest:testFuzzRecoverWithValidSignature(string,string) (runs: 256, μ: 21790, ~: 21796) +ECDSATest:testFuzzRecoverWithWrongMessage(string,string,bytes32) (runs: 256, μ: 21778, ~: 21789) +ECDSATest:testFuzzToDataWithIntendedValidatorHash(address,bytes) (runs: 256, μ: 7069, ~: 7057) +ECDSATest:testFuzzToDataWithIntendedValidatorHashSelf(bytes) (runs: 256, μ: 10062, ~: 10045) ECDSATest:testFuzzToTypedDataHash(string,string) (runs: 256, μ: 7105, ~: 7108) -ECDSATest:testRecoverWith0x00Value() (gas: 15565) -ECDSATest:testRecoverWithArbitraryMessage() (gas: 20568) -ECDSATest:testRecoverWithCorrectVersion() (gas: 21317) -ECDSATest:testRecoverWithInvalidSignature() (gas: 15217) -ECDSATest:testRecoverWithTooHighSValue() (gas: 15572) -ECDSATest:testRecoverWithTooLongSignature() (gas: 12197) -ECDSATest:testRecoverWithTooShortSignature() (gas: 13956) -ECDSATest:testRecoverWithValidSignature() (gas: 20562) -ECDSATest:testRecoverWithWrongMessage() (gas: 20624) -ECDSATest:testRecoverWithWrongVersion() (gas: 15615) -ECDSATest:testToTypedDataHash() (gas: 5905) +ECDSATest:testRecoverWith0x00Value() (gas: 15623) +ECDSATest:testRecoverWithArbitraryMessage() (gas: 20655) +ECDSATest:testRecoverWithCorrectVersion() (gas: 21404) +ECDSATest:testRecoverWithInvalidSignature() (gas: 15297) +ECDSATest:testRecoverWithTooHighSValue() (gas: 15697) +ECDSATest:testRecoverWithTooLongSignature() (gas: 12226) +ECDSATest:testRecoverWithTooShortSignature() (gas: 13963) +ECDSATest:testRecoverWithValidSignature() (gas: 20649) +ECDSATest:testRecoverWithWrongMessage() (gas: 20711) +ECDSATest:testRecoverWithWrongVersion() (gas: 15673) +ECDSATest:testToDataWithIntendedValidatorHash() (gas: 11377) +ECDSATest:testToDataWithIntendedValidatorHashSelf() (gas: 10220) +ECDSATest:testToTypedDataHash() (gas: 5973) EIP712DomainSeparatorTest:testCachedDomainSeparatorV4() (gas: 7554) EIP712DomainSeparatorTest:testDomainSeparatorV4() (gas: 9332) -EIP712DomainSeparatorTest:testFuzzDomainSeparatorV4(uint8) (runs: 256, μ: 9444, ~: 9473) +EIP712DomainSeparatorTest:testFuzzDomainSeparatorV4(uint8) (runs: 256, μ: 9445, ~: 9473) EIP712DomainSeparatorTest:testFuzzHashTypedDataV4(address,address,uint256,uint256,uint64) (runs: 256, μ: 7971, ~: 7971) EIP712DomainSeparatorTest:testHashTypedDataV4() (gas: 13313) ERC1155Invariants:invariantOwner() (runs: 256, calls: 3840, reverts: 3479) @@ -353,108 +357,108 @@ ERC20Test:testTransferToZeroAddress() (gas: 16812) ERC20Test:testTransferZeroTokens() (gas: 25327) ERC721Invariants:invariantOwner() (runs: 256, calls: 3840, reverts: 3449) ERC721Invariants:invariantTotalSupply() (runs: 256, calls: 3840, reverts: 3449) -ERC721Test:testApproveClearingApprovalWithNoPriorApproval() (gas: 177983) -ERC721Test:testApproveClearingApprovalWithPriorApproval() (gas: 187617) -ERC721Test:testApproveFromApprovedAddress() (gas: 200709) -ERC721Test:testApproveFromNonOwner() (gas: 173680) -ERC721Test:testApproveFromOperatorAddress() (gas: 225161) -ERC721Test:testApproveInvalidTokenId() (gas: 171657) -ERC721Test:testApproveToOwner() (gas: 168051) -ERC721Test:testApproveToZeroAddress() (gas: 187616) -ERC721Test:testApproveWithNoPriorApproval() (gas: 197450) -ERC721Test:testApproveWithPriorApprovalToDifferentAddress() (gas: 207111) -ERC721Test:testApproveWithPriorApprovalToSameAddress() (gas: 205480) -ERC721Test:testBalanceOfCase1() (gas: 328453) +ERC721Test:testApproveClearingApprovalWithNoPriorApproval() (gas: 179010) +ERC721Test:testApproveClearingApprovalWithPriorApproval() (gas: 188644) +ERC721Test:testApproveFromApprovedAddress() (gas: 201736) +ERC721Test:testApproveFromNonOwner() (gas: 174707) +ERC721Test:testApproveFromOperatorAddress() (gas: 226188) +ERC721Test:testApproveInvalidTokenId() (gas: 172684) +ERC721Test:testApproveToOwner() (gas: 169078) +ERC721Test:testApproveToZeroAddress() (gas: 188643) +ERC721Test:testApproveWithNoPriorApproval() (gas: 198477) +ERC721Test:testApproveWithPriorApprovalToDifferentAddress() (gas: 208138) +ERC721Test:testApproveWithPriorApprovalToSameAddress() (gas: 206507) +ERC721Test:testBalanceOfCase1() (gas: 330507) ERC721Test:testBalanceOfCase2() (gas: 11982) ERC721Test:testBalanceOfZeroAddress() (gas: 11088) -ERC721Test:testBurnSuccess() (gas: 307446) -ERC721Test:testBurnSuccessViaApproveAndSetApprovalForAll() (gas: 375144) +ERC721Test:testBurnSuccess() (gas: 309089) +ERC721Test:testBurnSuccessViaApproveAndSetApprovalForAll() (gas: 376788) ERC721Test:testCachedDomainSeparator() (gas: 8067) ERC721Test:testDomainSeparator() (gas: 11978) -ERC721Test:testFuzzApproveClearingApprovalWithNoPriorApproval(address,address) (runs: 256, μ: 197468, ~: 197478) -ERC721Test:testFuzzApproveClearingApprovalWithPriorApproval(address,address) (runs: 256, μ: 185644, ~: 185654) -ERC721Test:testFuzzApproveFromNonOwner(address) (runs: 256, μ: 173066, ~: 173066) -ERC721Test:testFuzzApproveFromOperatorAddress(address,address,address) (runs: 256, μ: 223802, ~: 223802) -ERC721Test:testFuzzApproveWithNoPriorApproval(address,address) (runs: 256, μ: 197468, ~: 197478) -ERC721Test:testFuzzApproveWithPriorApproval(address,address) (runs: 256, μ: 205501, ~: 205511) -ERC721Test:testFuzzBurnSuccess(address) (runs: 256, μ: 306772, ~: 306764) -ERC721Test:testFuzzDomainSeparator(uint8) (runs: 256, μ: 10071, ~: 10104) -ERC721Test:testFuzzGetApprovedApprovedTokenId(address,address) (runs: 256, μ: 195028, ~: 195038) -ERC721Test:testFuzzPermitInvalid(string,string,uint16) (runs: 256, μ: 203269, ~: 203305) -ERC721Test:testFuzzPermitSuccess(string,string,uint16) (runs: 256, μ: 229794, ~: 229837) +ERC721Test:testFuzzApproveClearingApprovalWithNoPriorApproval(address,address) (runs: 256, μ: 198495, ~: 198505) +ERC721Test:testFuzzApproveClearingApprovalWithPriorApproval(address,address) (runs: 256, μ: 186671, ~: 186681) +ERC721Test:testFuzzApproveFromNonOwner(address) (runs: 256, μ: 174093, ~: 174093) +ERC721Test:testFuzzApproveFromOperatorAddress(address,address,address) (runs: 256, μ: 224829, ~: 224829) +ERC721Test:testFuzzApproveWithNoPriorApproval(address,address) (runs: 256, μ: 198495, ~: 198505) +ERC721Test:testFuzzApproveWithPriorApproval(address,address) (runs: 256, μ: 206528, ~: 206538) +ERC721Test:testFuzzBurnSuccess(address) (runs: 256, μ: 308415, ~: 308407) +ERC721Test:testFuzzDomainSeparator(uint8) (runs: 256, μ: 10076, ~: 10104) +ERC721Test:testFuzzGetApprovedApprovedTokenId(address,address) (runs: 256, μ: 196055, ~: 196065) +ERC721Test:testFuzzPermitInvalid(string,string,uint16) (runs: 256, μ: 204301, ~: 204332) +ERC721Test:testFuzzPermitSuccess(string,string,uint16) (runs: 256, μ: 230826, ~: 230864) ERC721Test:testFuzzRenounceOwnershipNonOwner(address) (runs: 256, μ: 14408, ~: 14408) ERC721Test:testFuzzRenounceOwnershipSuccess(address) (runs: 256, μ: 49498, ~: 49482) ERC721Test:testFuzzSafeMintNonMinter(address) (runs: 256, μ: 16197, ~: 16197) -ERC721Test:testFuzzSafeMintSuccess(address[]) (runs: 256, μ: 21171305, ~: 21116709) -ERC721Test:testFuzzSafeTransferFromWithData(address,address,address,bytes) (runs: 256, μ: 1456566, ~: 1457269) -ERC721Test:testFuzzSetApprovalForAllSuccess(address,address) (runs: 256, μ: 190192, ~: 190192) -ERC721Test:testFuzzSetMinterNonOwner(address,string) (runs: 256, μ: 16190, ~: 16210) +ERC721Test:testFuzzSafeMintSuccess(address[]) (runs: 256, μ: 21484809, ~: 21429329) +ERC721Test:testFuzzSafeTransferFromWithData(address,address,address,bytes) (runs: 256, μ: 1458209, ~: 1458913) +ERC721Test:testFuzzSetApprovalForAllSuccess(address,address) (runs: 256, μ: 191219, ~: 191219) +ERC721Test:testFuzzSetMinterNonOwner(address,string) (runs: 256, μ: 16192, ~: 16210) ERC721Test:testFuzzSetMinterSuccess(string) (runs: 256, μ: 34775, ~: 34772) -ERC721Test:testFuzzTokenByIndex(address,string[]) (runs: 256, μ: 24077371, ~: 24464364) -ERC721Test:testFuzzTotalSupply(address,string[]) (runs: 256, μ: 23844114, ~: 24225068) -ERC721Test:testFuzzTransferFrom(address,address,address) (runs: 256, μ: 570035, ~: 570019) +ERC721Test:testFuzzTokenByIndex(address,string[]) (runs: 256, μ: 24213046, ~: 24635126) +ERC721Test:testFuzzTotalSupply(address,string[]) (runs: 256, μ: 23979788, ~: 24395829) +ERC721Test:testFuzzTransferFrom(address,address,address) (runs: 256, μ: 571678, ~: 571662) ERC721Test:testFuzzTransferOwnershipNonOwner(address,address) (runs: 256, μ: 14485, ~: 14485) ERC721Test:testFuzzTransferOwnershipSuccess(address,address) (runs: 256, μ: 77186, ~: 77167) -ERC721Test:testGetApprovedApprovedTokenId() (gas: 194965) +ERC721Test:testGetApprovedApprovedTokenId() (gas: 195992) ERC721Test:testGetApprovedInvalidTokenId() (gas: 11220) -ERC721Test:testGetApprovedNotApprovedTokenId() (gas: 170476) +ERC721Test:testGetApprovedNotApprovedTokenId() (gas: 171503) ERC721Test:testHasOwner() (gas: 10285) -ERC721Test:testInitialSetup() (gas: 2452715) -ERC721Test:testOwnerOf() (gas: 166028) +ERC721Test:testInitialSetup() (gas: 2471464) +ERC721Test:testOwnerOf() (gas: 167055) ERC721Test:testOwnerOfInvalidTokenId() (gas: 11130) -ERC721Test:testPermitBadChainId() (gas: 201261) -ERC721Test:testPermitBadNonce() (gas: 198344) -ERC721Test:testPermitExpiredDeadline() (gas: 171222) -ERC721Test:testPermitOtherSignature() (gas: 199716) -ERC721Test:testPermitReplaySignature() (gas: 233227) -ERC721Test:testPermitSuccess() (gas: 228734) +ERC721Test:testPermitBadChainId() (gas: 202288) +ERC721Test:testPermitBadNonce() (gas: 199371) +ERC721Test:testPermitExpiredDeadline() (gas: 172249) +ERC721Test:testPermitOtherSignature() (gas: 200743) +ERC721Test:testPermitReplaySignature() (gas: 234254) +ERC721Test:testPermitSuccess() (gas: 229761) ERC721Test:testRenounceOwnershipNonOwner() (gas: 11345) ERC721Test:testRenounceOwnershipSuccess() (gas: 23646) ERC721Test:testSafeMintNonMinter() (gas: 13591) ERC721Test:testSafeMintOverflow() (gas: 15814) -ERC721Test:testSafeMintReceiverContract() (gas: 392834) +ERC721Test:testSafeMintReceiverContract() (gas: 393861) ERC721Test:testSafeMintReceiverContractFunctionNotImplemented() (gas: 116912) ERC721Test:testSafeMintReceiverContractInvalidReturnIdentifier() (gas: 345758) ERC721Test:testSafeMintReceiverContractRevertsWithMessage() (gas: 343028) ERC721Test:testSafeMintReceiverContractRevertsWithPanic() (gas: 343253) ERC721Test:testSafeMintReceiverContractRevertsWithoutMessage() (gas: 342634) -ERC721Test:testSafeMintSuccess() (gas: 519349) +ERC721Test:testSafeMintSuccess() (gas: 529746) ERC721Test:testSafeMintToZeroAddress() (gas: 38767) -ERC721Test:testSafeMintTokenAlreadyMinted() (gas: 360132) -ERC721Test:testSafeTransferFromNoData() (gas: 1458870) -ERC721Test:testSafeTransferFromReceiverFunctionNotImplemented() (gas: 183065) -ERC721Test:testSafeTransferFromReceiverInvalidReturnIdentifier() (gas: 411906) -ERC721Test:testSafeTransferFromReceiverRevertsWithMessage() (gas: 409221) -ERC721Test:testSafeTransferFromReceiverRevertsWithPanic() (gas: 409491) -ERC721Test:testSafeTransferFromReceiverRevertsWithoutMessage() (gas: 408783) -ERC721Test:testSafeTransferFromWithData() (gas: 1221164) -ERC721Test:testSetApprovalForAllOperatorIsOwner() (gas: 167581) -ERC721Test:testSetApprovalForAllSuccessCase1() (gas: 196296) -ERC721Test:testSetApprovalForAllSuccessCase2() (gas: 190149) -ERC721Test:testSetApprovalForAllSuccessCase3() (gas: 203239) +ERC721Test:testSafeMintTokenAlreadyMinted() (gas: 365299) +ERC721Test:testSafeTransferFromNoData() (gas: 1460513) +ERC721Test:testSafeTransferFromReceiverFunctionNotImplemented() (gas: 184092) +ERC721Test:testSafeTransferFromReceiverInvalidReturnIdentifier() (gas: 412933) +ERC721Test:testSafeTransferFromReceiverRevertsWithMessage() (gas: 410248) +ERC721Test:testSafeTransferFromReceiverRevertsWithPanic() (gas: 410518) +ERC721Test:testSafeTransferFromReceiverRevertsWithoutMessage() (gas: 409810) +ERC721Test:testSafeTransferFromWithData() (gas: 1222808) +ERC721Test:testSetApprovalForAllOperatorIsOwner() (gas: 168608) +ERC721Test:testSetApprovalForAllSuccessCase1() (gas: 197323) +ERC721Test:testSetApprovalForAllSuccessCase2() (gas: 191176) +ERC721Test:testSetApprovalForAllSuccessCase3() (gas: 204266) ERC721Test:testSetMinterNonOwner() (gas: 13033) ERC721Test:testSetMinterRemoveOwnerAddress() (gas: 14220) ERC721Test:testSetMinterSuccess() (gas: 34584) ERC721Test:testSetMinterToZeroAddress() (gas: 16072) ERC721Test:testSupportsInterfaceGasCost() (gas: 5759) -ERC721Test:testSupportsInterfaceInvalidInterfaceId() (gas: 5665) -ERC721Test:testSupportsInterfaceSuccess() (gas: 9479) -ERC721Test:testTokenByIndex() (gas: 559639) -ERC721Test:testTokenByIndexOutOfBounds() (gas: 330858) -ERC721Test:testTokenOfOwnerByIndex() (gas: 580824) -ERC721Test:testTokenOfOwnerByIndexReverts() (gas: 553243) -ERC721Test:testTokenURIAfterBurning() (gas: 139160) -ERC721Test:testTokenURIDefault() (gas: 169125) +ERC721Test:testSupportsInterfaceInvalidInterfaceId() (gas: 5688) +ERC721Test:testSupportsInterfaceSuccess() (gas: 10447) +ERC721Test:testTokenByIndex() (gas: 563747) +ERC721Test:testTokenByIndexOutOfBounds() (gas: 332912) +ERC721Test:testTokenOfOwnerByIndex() (gas: 584932) +ERC721Test:testTokenOfOwnerByIndexReverts() (gas: 556324) +ERC721Test:testTokenURIAfterBurning() (gas: 139981) +ERC721Test:testTokenURIDefault() (gas: 170152) ERC721Test:testTokenURIInvalidTokenId() (gas: 11705) -ERC721Test:testTokenURINoBaseURI() (gas: 2570496) -ERC721Test:testTokenURINoTokenUri() (gas: 126199) -ERC721Test:testTotalSupply() (gas: 328461) -ERC721Test:testTransferFrom() (gas: 580916) +ERC721Test:testTokenURINoBaseURI() (gas: 2590272) +ERC721Test:testTokenURINoTokenUri() (gas: 127226) +ERC721Test:testTotalSupply() (gas: 330515) +ERC721Test:testTransferFrom() (gas: 582560) ERC721Test:testTransferOwnershipNonOwner() (gas: 13015) ERC721Test:testTransferOwnershipSuccess() (gas: 55029) ERC721Test:testTransferOwnershipToZeroAddress() (gas: 16064) -MerkleProofVerificationTest:testFuzzMultiProofVerifySingleLeaf(bytes32[],uint256) (runs: 256, μ: 1649977829, ~: 1649974658) -MerkleProofVerificationTest:testFuzzVerify(bytes32[],uint256) (runs: 256, μ: 135976484, ~: 135973284) +MerkleProofVerificationTest:testFuzzMultiProofVerifySingleLeaf(bytes32[],uint256) (runs: 256, μ: 1649977830, ~: 1649974618) +MerkleProofVerificationTest:testFuzzVerify(bytes32[],uint256) (runs: 256, μ: 135976485, ~: 135973244) MerkleProofVerificationTest:testFuzzVerifyMultiProofMultipleLeaves(bool,bool,bool) (runs: 256, μ: 412472500, ~: 412472432) MerkleProofVerificationTest:testInvalidMerkleMultiProof() (gas: 412478563) MerkleProofVerificationTest:testInvalidMerkleProof() (gas: 33970453) @@ -507,7 +511,7 @@ OwnableTest:testTransferOwnershipNonOwner() (gas: 12551) OwnableTest:testTransferOwnershipSuccess() (gas: 22089) OwnableTest:testTransferOwnershipToZeroAddress() (gas: 15512) SignatureCheckerTest:testEIP1271NoIsValidSignatureFunction() (gas: 22865) -SignatureCheckerTest:testEIP1271WithInvalidSignature(bytes,string) (runs: 256, μ: 23606, ~: 23598) +SignatureCheckerTest:testEIP1271WithInvalidSignature(bytes,string) (runs: 256, μ: 23605, ~: 23598) SignatureCheckerTest:testEIP1271WithInvalidSignature1() (gas: 33857) SignatureCheckerTest:testEIP1271WithInvalidSignature2() (gas: 29023) SignatureCheckerTest:testEIP1271WithInvalidSigner() (gas: 33935) @@ -518,8 +522,8 @@ SignatureCheckerTest:testEOAWithInvalidSignature2() (gas: 20267) SignatureCheckerTest:testEOAWithInvalidSigner() (gas: 20496) SignatureCheckerTest:testEOAWithTooHighSValue() (gas: 17256) SignatureCheckerTest:testEOAWithValidSignature() (gas: 19591) -SignatureCheckerTest:testFuzzEIP1271WithInvalidSigner(string,string) (runs: 256, μ: 35896, ~: 35902) +SignatureCheckerTest:testFuzzEIP1271WithInvalidSigner(string,string) (runs: 256, μ: 35895, ~: 35902) SignatureCheckerTest:testFuzzEIP1271WithValidSignature(string) (runs: 256, μ: 34429, ~: 34431) SignatureCheckerTest:testFuzzEOAWithInvalidSignature(bytes,string) (runs: 256, μ: 16901, ~: 16896) -SignatureCheckerTest:testFuzzEOAWithInvalidSigner(string,string) (runs: 256, μ: 21577, ~: 21583) -SignatureCheckerTest:testFuzzEOAWithValidSignature(string,string) (runs: 256, μ: 20688, ~: 20694) \ No newline at end of file +SignatureCheckerTest:testFuzzEOAWithInvalidSigner(string,string) (runs: 256, μ: 21576, ~: 21583) +SignatureCheckerTest:testFuzzEOAWithValidSignature(string,string) (runs: 256, μ: 20687, ~: 20694) \ No newline at end of file diff --git a/lib/create-util b/lib/create-util index 805c664c..e1ebc2e9 160000 --- a/lib/create-util +++ b/lib/create-util @@ -1 +1 @@ -Subproject commit 805c664c182fbf4b6588a008a67173d16a2ed53c +Subproject commit e1ebc2e93df0e18b50a2cd3b7323bdc3373c5a8a diff --git a/lib/forge-std b/lib/forge-std index a2edd39d..5bbb2aa8 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit a2edd39db95df7e9dd3f9ef9edc8c55fefddb6df +Subproject commit 5bbb2aa82d86456dbf03305c3704cbd4fa93473f diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index 96a2297e..adb861fb 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 96a2297e15f1a4bbcf470d2d0d6cb9c579c63893 +Subproject commit adb861fb3bb4b4167f10307b8d091326115502f9 diff --git a/lib/prb-test b/lib/prb-test index 2c767827..fa795366 160000 --- a/lib/prb-test +++ b/lib/prb-test @@ -1 +1 @@ -Subproject commit 2c7678271c450c88e76cf50d3b8a9314344a0475 +Subproject commit fa795366244b24c34896ac59f1b97d92dc022175 diff --git a/src/utils/ECDSA.vy b/src/utils/ECDSA.vy index ec30665c..d223bbcd 100644 --- a/src/utils/ECDSA.vy +++ b/src/utils/ECDSA.vy @@ -4,8 +4,10 @@ @license GNU Affero General Public License v3.0 @author pcaversaccio @notice These functions can be used to verify that a message was signed - by the holder of the private key of a given address. The implementation - is inspired by OpenZeppelin's implementation here: + by the holder of the private key of a given address. Additionally, + we provide helper functions to handle signed data in Ethereum + contracts based on EIP-191: https://eips.ethereum.org/EIPS/eip-191. + The implementation is inspired by OpenZeppelin's implementation here: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol. @custom:security Signatures must not be used as unique identifiers since the `ecrecover` opcode allows for malleable (non-unique) signatures. @@ -16,6 +18,12 @@ _MALLEABILITY_THRESHOLD: constant(bytes32) = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 _SIGNATURE_INCREMENT: constant(bytes32) = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +# @dev A Vyper contract cannot call directly between two `external` functions. +# To bypass this, we can use an interface. +interface IECDSA: + def to_data_with_intended_validator_hash(validator: address, data: Bytes[1024]) -> bytes32: pure + + @external @payable def __init__(): @@ -65,6 +73,77 @@ def recover_sig(hash: bytes32, signature: Bytes[65]) -> address: return empty(address) +@external +@pure +def to_eth_signed_message_hash(hash: bytes32) -> bytes32: + """ + @dev Returns an Ethereum signed message from a 32-byte + message digest `hash`. + @notice This function returns a 32-byte hash that + corresponds to the one signed with the JSON-RPC method: + https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign. + This method is part of EIP-191: + https://eips.ethereum.org/EIPS/eip-191. + @param hash The 32-byte message digest. + @return bytes32 The 32-byte Ethereum signed message. + """ + return keccak256(concat(b"\x19Ethereum Signed Message:\n32", hash)) + + +@external +@pure +def to_typed_data_hash(domain_separator: bytes32, struct_hash: bytes32) -> bytes32: + """ + @dev Returns an Ethereum signed typed data from a 32-byte + `domain_separator` and a 32-byte `struct_hash`. + @notice This function returns a 32-byte hash that + corresponds to the one signed with the JSON-RPC method: + https://eips.ethereum.org/EIPS/eip-712#specification-of-the-eth_signtypeddata-json-rpc. + This method is part of EIP-712: + https://eips.ethereum.org/EIPS/eip-712. + @param domain_separator The 32-byte domain separator that is + used as part of the EIP-712 encoding scheme. + @param struct_hash The 32-byte struct hash that is used as + part of the EIP-712 encoding scheme. See the definition: + https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct. + @return bytes32 The 32-byte Ethereum signed typed data. + """ + return keccak256(concat(b"\x19\x01", domain_separator, struct_hash)) + + +@external +@view +def to_data_with_intended_validator_hash_self(data: Bytes[1024]) -> bytes32: + """ + @dev Returns an Ethereum signed data with this contract + as the intended validator and a maximum 1024-byte + payload `data`. + @notice This function structures the data according to + the version `0x00` of EIP-191: + https://eips.ethereum.org/EIPS/eip-191#version-0x00. + @param data The maximum 1024-byte data to be signed. + @return bytes32 The 32-byte Ethereum signed data. + """ + return IECDSA(self).to_data_with_intended_validator_hash(self, data) + + +@external +@pure +def to_data_with_intended_validator_hash(validator: address, data: Bytes[1024]) -> bytes32: + """ + @dev Returns an Ethereum signed data with `validator` as + the intended validator and a maximum 1024-byte payload + `data`. + @notice This function structures the data according to + the version `0x00` of EIP-191: + https://eips.ethereum.org/EIPS/eip-191#version-0x00. + @param validator The 20-byte intended validator address. + @param data The maximum 1024-byte data to be signed. + @return bytes32 The 32-byte Ethereum signed data. + """ + return keccak256(concat(b"\x19\x00", convert(validator, bytes20), data)) + + @internal @pure def _recover_vrs(hash: bytes32, v: uint256, r: uint256, s: uint256) -> address: @@ -126,41 +205,3 @@ def _try_recover_vrs(hash: bytes32, v: uint256, r: uint256, s: uint256) -> addre raise "ECDSA: invalid signature" return signer - - -@external -@pure -def to_eth_signed_message_hash(hash: bytes32) -> bytes32: - """ - @dev Returns an Ethereum signed message from a 32-byte - message digest `hash`. - @notice This function returns a 32-byte hash that - corresponds to the one signed with the JSON-RPC method: - https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign. - This method is part of EIP-191: - https://eips.ethereum.org/EIPS/eip-191. - @param hash The 32-byte message digest. - @return bytes32 The 32-byte Ethereum signed message. - """ - return keccak256(concat(b"\x19Ethereum Signed Message:\n32", hash)) - - -@external -@pure -def to_typed_data_hash(domain_separator: bytes32, struct_hash: bytes32) -> bytes32: - """ - @dev Returns an Ethereum signed typed data from a 32-byte - `domain_separator` and a 32-byte `struct_hash`. - @notice This function returns a 32-byte hash that - corresponds to the one signed with the JSON-RPC method: - https://eips.ethereum.org/EIPS/eip-712#specification-of-the-eth_signtypeddata-json-rpc. - This method is part of EIP-712: - https://eips.ethereum.org/EIPS/eip-712. - @param domain_separator The 32-byte domain separator that is - used as part of the EIP-712 encoding scheme. - @param struct_hash The 32-byte struct hash that is used as - part of the EIP-712 encoding scheme. See the definition: - https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct. - @return bytes32 The 32-byte Ethereum signed typed data. - """ - return keccak256(concat(b"\x19\x01", domain_separator, struct_hash)) diff --git a/test/utils/ECDSA.t.sol b/test/utils/ECDSA.t.sol index f7ab6f8b..d7ddaa7e 100644 --- a/test/utils/ECDSA.t.sol +++ b/test/utils/ECDSA.t.sol @@ -30,6 +30,8 @@ contract ECDSATest is Test { address private self = address(this); address private zeroAddress = address(0); + // solhint-disable-next-line var-name-mixedcase + address private ECDSAAddr; /** * @dev Transforms a standard signature into an EIP-2098 @@ -50,6 +52,7 @@ contract ECDSATest is Test { function setUp() public { ECDSA = IECDSA(vyperDeployer.deployContract("src/utils/", "ECDSA")); + ECDSAAddr = address(ECDSA); } function testRecoverWithValidSignature() public { @@ -252,6 +255,28 @@ contract ECDSATest is Test { assertEq(digest1, digest2); } + function testToDataWithIntendedValidatorHash() public { + address validator = makeAddr("intendedValidator"); + bytes memory data = new bytes(42); + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash( + validator, + data + ); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", validator, data) + ); + assertEq(digest1, digest2); + } + + function testToDataWithIntendedValidatorHashSelf() public { + bytes memory data = new bytes(42); + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash_self(data); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", ECDSAAddr, data) + ); + assertEq(digest1, digest2); + } + function testFuzzRecoverWithValidSignature( string calldata signer, string calldata message @@ -357,4 +382,28 @@ contract ECDSATest is Test { ); assertEq(digest1, digest2); } + + function testFuzzToDataWithIntendedValidatorHash( + address validator, + bytes calldata data + ) public { + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash( + validator, + data + ); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", validator, data) + ); + assertEq(digest1, digest2); + } + + function testFuzzToDataWithIntendedValidatorHashSelf( + bytes calldata data + ) public { + bytes32 digest1 = ECDSA.to_data_with_intended_validator_hash_self(data); + bytes32 digest2 = keccak256( + abi.encodePacked("\x19\x00", ECDSAAddr, data) + ); + assertEq(digest1, digest2); + } } diff --git a/test/utils/interfaces/IECDSA.sol b/test/utils/interfaces/IECDSA.sol index eff5e094..641593a2 100644 --- a/test/utils/interfaces/IECDSA.sol +++ b/test/utils/interfaces/IECDSA.sol @@ -15,4 +15,13 @@ interface IECDSA { bytes32 domainSeparator, bytes32 structHash ) external pure returns (bytes32); + + function to_data_with_intended_validator_hash_self( + bytes calldata data + ) external view returns (bytes32); + + function to_data_with_intended_validator_hash( + address validator, + bytes calldata data + ) external pure returns (bytes32); }