Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps: bump openzeppelin to 5.2.0 and remove our own impls #209

Merged
merged 3 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,10 @@ The following benchmarks are for a single packet transfer without aggregation.
| **Contract** | **Method** | **Description** | **Gas (groth16)** | **Gas (plonk)** |
|:---:|:---:|:---:|:---:|:---:|
| `ICS26Router.sol` | `sendPacket` | Initiating an IBC transfer with an `ERC20`. | ~186,808 | ~186,808 |
| `ICS26Router.sol` | `recvPacket` | Receiving _back_ an `ERC20` token. | ~541,800 | ~626,140 |
| `ICS26Router.sol` | `recvPacket` | Receiving a _new_ Cosmos token for the first time. (Deploying an `ERC20` contract) | ~1,436,748 | ~1,520,226 |
| `ICS26Router.sol` | `ackPacket` | Acknowledging an ICS20 packet. | ~419,121 | ~502,895 |
| `ICS26Router.sol` | `timeoutPacket` | Timing out an ICS20 packet | ~471,313 | ~554,696 |
| `ICS26Router.sol` | `recvPacket` | Receiving _back_ an `ERC20` token. | ~492,600 | ~566,800 |
| `ICS26Router.sol` | `recvPacket` | Receiving a _new_ Cosmos token for the first time. (Deploying an `ERC20` contract) | ~1,400,000 | ~1,480,950 |
| `ICS26Router.sol` | `ackPacket` | Acknowledging an ICS20 packet. | ~367,000 | ~442,700 |
| `ICS26Router.sol` | `timeoutPacket` | Timing out an ICS20 packet | ~432,400 | ~506,000 |

### Aggregated Packet Benchmarks

Expand All @@ -175,8 +175,8 @@ Since there is no meaningful difference in gas costs between plonk and groth16 i

| **ICS26Router Method** | **Description** | **Avg Gas (25 packets)** | **Avg Gas (50 packets)** |
|:---:|:---:|:---:|:---:|
| `multicall/recvPacket` | Receiving _back_ an `ERC20` token. | ~198,341 | ~191,618 |
| `multicall/ackPacket` | Acknowledging an ICS20 packet. | ~105,336 | ~99,365 |
| `multicall/recvPacket` | Receiving _back_ an `ERC20` token. | ~185,003 | ~178,772 |
| `multicall/ackPacket` | Acknowledging an ICS20 packet. | ~95,650 | ~90,225 |

Note: These gas benchmarks are with Groth16.

Expand Down
32 changes: 0 additions & 32 deletions abi/ICS20Transfer.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,38 +594,6 @@
"name": "ICS20AbiEncodingFailure",
"inputs": []
},
{
"type": "error",
"name": "ICS20BytesSliceOutOfBounds",
"inputs": [
{
"name": "length",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "start",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "end",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "ICS20BytesSliceOverflow",
"inputs": [
{
"name": "length",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "ICS20DenomNotFound",
Expand Down
2 changes: 1 addition & 1 deletion abigen/ics20transfer/contract.go

Large diffs are not rendered by default.

Binary file modified bun.lockb
Binary file not shown.
4 changes: 2 additions & 2 deletions contracts/ICS20Transfer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { IICS26Router } from "./interfaces/IICS26Router.sol";
import { IICS26RouterMsgs } from "./msgs/IICS26RouterMsgs.sol";
import { IBCERC20 } from "./utils/IBCERC20.sol";
import { Escrow } from "./utils/Escrow.sol";
import { Bytes } from "@openzeppelin/utils/Bytes.sol";

using SafeERC20 for IERC20;

Expand Down Expand Up @@ -275,8 +276,7 @@ contract ICS20Transfer is
erc20Address = findOrCreateERC20Address(fullDenomPath, baseDenom);
} else {
// we are the source of this token: we remove the source prefix and expect the denom to be an erc20 address
string memory erc20AddressStr =
string(ICS20Lib.slice(denomBz, sourceDenomPrefix.length, denomBz.length - sourceDenomPrefix.length));
string memory erc20AddressStr = string(Bytes.slice(denomBz, sourceDenomPrefix.length));
erc20Address = ICS20Lib.mustHexStringToAddress(erc20AddressStr);
}

Expand Down
10 changes: 0 additions & 10 deletions contracts/errors/IICS20Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,4 @@ interface IICS20Errors {

/// @notice Abi encoding/decoding failure
error ICS20AbiEncodingFailure();

/// @notice Bytes slice overflow
/// @param length length of the slice
error ICS20BytesSliceOverflow(uint256 length);

/// @notice Bytes slice out of bounds
/// @param length length of the bytes
/// @param start start index
/// @param end end index
error ICS20BytesSliceOutOfBounds(uint256 length, uint256 start, uint256 end);
}
97 changes: 5 additions & 92 deletions contracts/utils/ICS20Lib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.28;
// solhint-disable no-inline-assembly

import { Strings } from "@openzeppelin/utils/Strings.sol";
import { Bytes } from "@openzeppelin/utils/Bytes.sol";
import { IICS20Errors } from "../errors/IICS20Errors.sol";
import { IICS26RouterMsgs } from "../msgs/IICS26RouterMsgs.sol";
import { IICS20TransferMsgs } from "../msgs/IICS20TransferMsgs.sol";
Expand Down Expand Up @@ -112,107 +113,19 @@ library ICS20Lib {
/// @return address value
/// @return true if the conversion was successful
function hexStringToAddress(string memory addrHexString) internal pure returns (address, bool) {
bytes memory addrBytes = bytes(addrHexString);
if (addrBytes.length != 42) {
return (address(0), false);
} else if (addrBytes[0] != "0" || addrBytes[1] != "x") {
return (address(0), false);
}
uint256 addr = 0;
unchecked {
for (uint256 i = 2; i < 42; i++) {
uint256 c = uint256(uint8(addrBytes[i]));
if (c >= 48 && c <= 57) {
addr = addr * 16 + (c - 48);
} else if (c >= 97 && c <= 102) {
addr = addr * 16 + (c - 87);
} else if (c >= 65 && c <= 70) {
addr = addr * 16 + (c - 55);
} else {
return (address(0), false);
}
}
}
return (address(uint160(addr)), true);
(bool success, address addr) = Strings.tryParseAddress(addrHexString);
return (addr, success);
}

/// @notice mustHexStringToAddress converts a hex string to an address and reverts on failure.
/// @param addrHexString hex address string
/// @return address the converted address
function mustHexStringToAddress(string memory addrHexString) internal pure returns (address) {
(address addr, bool success) = hexStringToAddress(addrHexString);
(bool success, address addr) = Strings.tryParseAddress(addrHexString);
require(success, IICS20Errors.ICS20InvalidAddress(addrHexString));
return addr;
}

/// @notice slice returns a slice of the original bytes from `start` to `start + length`.
/// @dev This is a copy from https://github.com/GNSPS/solidity-bytes-utils/blob/v0.8.0/contracts/BytesLib.sol
/// @param _bytes bytes
/// @param _start start index
/// @param _length length
/// @return sliced bytes
function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
if (_length + 31 < _length) {
revert IICS20Errors.ICS20BytesSliceOverflow(_length);
} else if (_start + _length > _bytes.length) {
revert IICS20Errors.ICS20BytesSliceOutOfBounds(_bytes.length, _start, _start + _length);
}

bytes memory tempBytes;

assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)

// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)

// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)

for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} { mstore(mc, mload(cc)) }

mstore(tempBytes, _length)

//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
//zero out the 32 bytes slice we are about to return
//we need to do it because Solidity does not garbage collect
mstore(tempBytes, 0)

mstore(0x40, add(tempBytes, 0x20))
}
}

return tempBytes;
}

/// @notice equal returns true if two byte arrays are equal.
/// @param a bytes
/// @param b bytes
Expand All @@ -229,7 +142,7 @@ library ICS20Lib {
if (denomBz.length < prefix.length) {
return false;
}
return equal(slice(denomBz, 0, prefix.length), prefix);
return equal(Bytes.slice(denomBz, 0, prefix.length), prefix);
}

/// @notice errorAck returns an error acknowledgement.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
"url": "https://github.com/srdtrk"
},
"dependencies": {
"@openzeppelin/contracts": "^5.1.0"
"@openzeppelin/contracts": "^5.2.0"
},
"devDependencies": {
"sp1-contracts": "github:succinctlabs/sp1-contracts#275691af9bfaf67158f6df1f4c3c1646eb03eed0",
"forge-std": "github:foundry-rs/forge-std#v1.9.4",
"solhint": "^5.0.3",
"solhint": "^5.0.4",
"@defi-wonderland/natspec-smells": "^1.1.5"
},
"keywords": [
Expand Down
Loading