Solidity Assembly

유지민·2022년 12월 6일
0

solidity

목록 보기
2/4

Assembly 쓰는 이유

  • 세밀한 조작
  • 가스비용 줄이기

솔리디티에서 할수없는 일을 할때 어셈블리어를 사용한다고 한다.
솔리디티 라이브러리 작성할떄 많이 사용한다고 한다.

Assembly 종류

  • 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

profile
개발 취준생

0개의 댓글