Skip to content

Commit

Permalink
♻️ Safe calldata copying (#1237)
Browse files Browse the repository at this point in the history
Co-authored-by: philogy <[email protected]>
  • Loading branch information
Vectorized and Philogy authored Dec 17, 2024
1 parent df3ed40 commit c312283
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 21 deletions.
38 changes: 22 additions & 16 deletions src/tokens/ERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ abstract contract ERC1155 {
mstore(add(m, 0x60), id)
mstore(add(m, 0x80), amount)
mstore(add(m, 0xa0), 0xa0)
calldatacopy(add(m, 0xc0), sub(data.offset, 0x20), add(0x20, data.length))
mstore(add(m, 0xc0), data.length)
calldatacopy(add(m, 0xe0), data.offset, data.length)
// Revert if the call reverts.
if iszero(call(gas(), to, 0, add(m, 0x1c), add(0xc4, data.length), m, 0x20)) {
if returndatasize() {
Expand Down Expand Up @@ -362,14 +363,16 @@ abstract contract ERC1155 {
let m := mload(0x40)
// Copy the `ids`.
mstore(m, 0x40)
let n := add(0x20, shl(5, ids.length))
let o := add(m, 0x40)
calldatacopy(o, sub(ids.offset, 0x20), n)
let n := shl(5, ids.length)
mstore(add(m, 0x40), ids.length)
calldatacopy(add(m, 0x60), ids.offset, n)
// Copy the `amounts`.
mstore(add(m, 0x20), add(0x40, n))
calldatacopy(add(o, n), sub(amounts.offset, 0x20), n)
mstore(add(m, 0x20), add(0x60, n))
let o := add(add(m, n), 0x60)
mstore(o, ids.length)
calldatacopy(add(o, 0x20), amounts.offset, n)
// Do the emit.
log4(m, add(add(n, n), 0x40), _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), from, to)
log4(m, add(add(n, n), 0x80), _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), from, to)
}
}
if (_useAfterTokenTransfer()) {
Expand All @@ -388,17 +391,20 @@ abstract contract ERC1155 {
mstore(add(m, 0x40), from)
// Copy the `ids`.
mstore(add(m, 0x60), 0xa0)
let n := add(0x20, shl(5, ids.length))
let o := add(m, 0xc0)
calldatacopy(o, sub(ids.offset, 0x20), n)
let n := shl(5, ids.length)
mstore(add(m, 0xc0), ids.length)
calldatacopy(add(m, 0xe0), ids.offset, n)
// Copy the `amounts`.
let s := add(0xa0, n)
mstore(add(m, 0x80), s)
calldatacopy(add(o, n), sub(amounts.offset, 0x20), n)
mstore(add(m, 0x80), add(0xc0, n))
let o := add(add(m, n), 0xe0)
mstore(o, ids.length)
calldatacopy(add(o, 0x20), amounts.offset, n)
// Copy the `data`.
mstore(add(m, 0xa0), add(s, n))
calldatacopy(add(o, add(n, n)), sub(data.offset, 0x20), add(0x20, data.length))
let nAll := add(0xc4, add(data.length, add(n, n)))
mstore(add(m, 0xa0), add(add(0xe0, n), n))
o := add(add(o, n), 0x20)
mstore(o, data.length)
calldatacopy(add(o, 0x20), data.offset, data.length)
let nAll := add(0x104, add(data.length, add(n, n)))
// Revert if the call reverts.
if iszero(call(gas(), mload(0x00), 0, add(m, 0x1c), nAll, m, 0x20)) {
if returndatasize() {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/LibTransient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ library LibTransient {
function setCalldata(TBytes storage ptr, bytes calldata value) internal {
/// @solidity memory-safe-assembly
assembly {
tstore(ptr.slot, calldataload(sub(value.offset, 0x04)))
tstore(ptr.slot, or(shl(224, value.length), shr(32, calldataload(value.offset))))
if iszero(lt(value.length, 0x1d)) {
mstore(0x00, ptr.slot)
let e := add(value.offset, value.length)
Expand All @@ -660,7 +660,7 @@ library LibTransient {
ptr = _compat(ptr);
/// @solidity memory-safe-assembly
assembly {
sstore(ptr.slot, calldataload(sub(value.offset, 0x04)))
sstore(ptr.slot, or(shl(224, value.length), shr(32, calldataload(value.offset))))
if iszero(lt(value.length, 0x1d)) {
mstore(0x00, ptr.slot)
let e := add(value.offset, value.length)
Expand Down
3 changes: 2 additions & 1 deletion src/utils/Lifebuoy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ contract Lifebuoy {
mstore(add(0x60, m), id) // Store the `id` argument.
mstore(add(0x80, m), amount) // Store the `amount` argument.
mstore(add(0xa0, m), 0xa0) // Store the offset to `data`.
calldatacopy(add(m, 0xc0), sub(data.offset, 0x20), add(0x20, data.length))
mstore(add(0xc0, m), data.length)
calldatacopy(add(m, 0xe0), data.offset, data.length)
// forgefmt: disable-next-item
if iszero(
call(gas(), token, callvalue(), add(m, 0x1c), add(0xc4, data.length), codesize(), 0x00)
Expand Down
4 changes: 2 additions & 2 deletions src/utils/g/LibTransient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ library LibTransient {
function setCalldata(TBytes storage ptr, bytes calldata value) internal {
/// @solidity memory-safe-assembly
assembly {
tstore(ptr.slot, calldataload(sub(value.offset, 0x04)))
tstore(ptr.slot, or(shl(224, value.length), shr(32, calldataload(value.offset))))
if iszero(lt(value.length, 0x1d)) {
mstore(0x00, ptr.slot)
let e := add(value.offset, value.length)
Expand All @@ -669,7 +669,7 @@ library LibTransient {
ptr = _compat(ptr);
/// @solidity memory-safe-assembly
assembly {
sstore(ptr.slot, calldataload(sub(value.offset, 0x04)))
sstore(ptr.slot, or(shl(224, value.length), shr(32, calldataload(value.offset))))
if iszero(lt(value.length, 0x1d)) {
mstore(0x00, ptr.slot)
let e := add(value.offset, value.length)
Expand Down

0 comments on commit c312283

Please sign in to comment.