- 세밀한 조작
- 가스비용 줄이기
솔리디티에서 할수없는 일을 할때 어셈블리어를 사용한다고 한다.
솔리디티 라이브러리 작성할떄 많이 사용한다고 한다.
- inline assembly : 솔리디티 안에 쓰인다.
- Standalone Assembly : 솔리디티 없이도 쓸 수 있다.
오늘 배운것은 인라인 어셈블리.
그치만 사용법이 어렵기 때문에 자주 오류가 날수있고 문서에도 자신이 있을떄만 사용할것을 권고.
contract ASSEMBLY {
//우리가 쓰는 간단한 더하기 같은 법이 어떻게 사용되는가
//솔리디티에서 못할떄 통용하려고 쓰는 어셈블리어
function uinttoBytes32(uint _a) public pure returns(bytes memory){
bytes memory b = new bytes(32); //new bytes(32);는 안정성을 위해해
// m store
assembly {
mstore(add(b, 32), _a)
}
// m(memory) store, s(storage) store (load(불러옴), store(저장))
return b;
}
function add(uint _a, uint _b) public pure returns(uint) {
assembly {
let result := add(_a, _b)
mstore(0x0, result)
return(0x0, 32)
}
}
function add2(uint _a, uint _b) public pure returns(uint) {
assembly {
let result := add(_a, add(_b, _b))
mstore(0x1, result) // 저장한곳과
return(0x0, 32) // 불러오는 곳이 달라서 리턴할수가 없음음
}
}
function mloadAsem() public pure returns(uint) {
assembly {
let a := 2
mstore(0x0, a)
let b :=mload(0x0)
mstore(0x10, b)
return (0x10, 32)
}
}
function mloadAsem2() public pure returns(uint) {
assembly {
let a := 2
let b := 3
let c := 4
mstore(0x0, a)
mstore(0x10, b)
mstore(0x15, c) //여기서 mstore를 실행하면 b가 0이 나온다. 왜? 휘발성이라서! 앞의 것들 다 날라감, 맨 마지막만 살아남긴다
//let d := mload(0x10)
return (0x15, 32) // 왜 0이 나오짐? 3아 나와야하는데? => 왜? 휘발성이라서! 앞의 것들 다 날라감, 맨 마지막만 살아남긴다.
//0x0, 0x10, 0x15 메모리 위치가 다른데 왜 다른 메모리 장소에 저장하면 이전 것들이 날아가나요? -> 메모라 자체를 한 통으로 일단 보자
}
}
uint aa = 1; // storage variable
//왜 안되는지 강사님이 확인후 다시 알려주심
function sloadsstore() public view returns(uint) {
assembly {
let b := aa.slot //aa를 갖고 오겠다 (.slot 빼면 Only local variables are supported. To access storage variables, use the ".slot" and ".offset" suffixes.)
mstore(0x10, b)
return(0x10, 32)
}
}
function sload2() public view returns(uint) {
assembly {
let c := sload(0)
mstore(0x80, c) //(위치, 값)
return(0x80, 32) //(위치, 어떤 형시으로 표현할 것 인가) 32바이트 (256 bits for 1 uint)
}
}
function sload3() public view returns(uint) {
assembly {
let c := sload(1)
mstore(0x80, c) //(위치, 값)
return(0x80, 32) //(위치, 어떤 형시으로 표현할 것 인가) 32바이트 (256 bits for 1 uint)
}
}
function arrayASSEM() public pure returns(uint[] memory) {
uint[] memory array = new uint[](3);
array[0] =1;
array[1] =2;
assembly {
let length := mload(array) // 배열 길이 가져오기기
let first := mload(add(array, 32)) // 배열 첫번째값 가져와서 넣기
let second := mload(add(array, 64)) // 배열 두번째값 가져와서 넣기
mstore(add(array, 96), add(first, second)) //first + second 를 배열 세번째에 넣기
//array[0]은 0~32
//array[1]은 33~64라고 이해하면되나요 -> 네
}
return array;
}
}
오피코드 참조용 사이트
https://www.evm.codes/?fork=merge