Skip to content

Instantly share code, notes, and snippets.

@reaperes
Last active December 14, 2023 09:21
Show Gist options
  • Save reaperes/737319ca04dc39696852d804e1a99e7e to your computer and use it in GitHub Desktop.
Save reaperes/737319ca04dc39696852d804e1a99e7e to your computer and use it in GitHub Desktop.
solidity assembly mload, add real-world example
pragma solidity ^0.8.9;
contract Simple {
function example() public pure {
address remote = 0x1111111111111111111111111111111111111111;
address local = 0x2222222222222222222222222222222222222222;
bytes memory path = abi.encodePacked(remote, local);
assembly {
return(0x00, x) // What number is suitable for x?
}
}
}
@reaperes
Copy link
Author

Answer is 200.

=====

다음은 example 함수를 실행시켰을때 메모리에 저장되는 데이터 입니다.

0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002811111111111111111111111111111111111111112222222222222222222222222222222222222222

0x 를 제외한 모든 글자는 400 자 입니다. 1 byte 를 16진수로 표기할 경우 2글자가 필요합니다. 따라서, 위의 글자들은 총 200 bytes 를 16 진수로 표기한 것으로 볼 수 있습니다.

위 데이터를 분해하면 다음과 같이 나누어질 수 있습니다.

[section 1 - solidity reserved space]
1-1: scratch space for hashing methods
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1-2: currently allocated memory size (aka. free memory pointer)
00000000000000000000000000000000000000000000000000000000000000c8
1-3: reserved space (zero slot)
0000000000000000000000000000000000000000000000000000000000000000

[section 2 - user memory space]
2-1: abi-encoded data
0000000000000000000000000000000000000000000000000000000000000028 (encoded 된 총 데이터 길이)
1111111111111111111111111111111111111111 (remote address)
2222222222222222222222222222222222222222 (local address)

만일 remote address 를 얻고 싶으면 assembly 코드를 다음과 같이 작성하면 됩니다.

assembly {
    return (add(path, 32), 20)
}

위 코드의 의미는 path 의 변수값이 저장된 메모리의 offset + 32 위치에서 20 bytes 만큼의 데이터를 리턴하라는 의미 입니다.
32는 데이터 길이를 나타내는 데이터 크기가 uint256(32 bytes)를 가지기 때문에 설정한 값이며,
20은 address 길이가 20 bytes (hex 의 경우 40 글자) 이기 때문에 설정되었습니다.

=====

예시의 개념은 실제 서비스 되는 코드들에서 사용되는 개념입니다. LayerZero contract 의 코드를 보면서 좀 더 이해의 폭을 넓힐 수 있습니다.
https://github.com/LayerZero-Labs/LayerZero/blob/main/contracts/UltraLightNodeV2.sol#L131

=====

references
[1] https://docs.soliditylang.org/en/latest/internals/layout_in_memory.html
[2] https://docs.soliditylang.org/en/develop/abi-spec.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment