일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 러스트 기초 학습
- 스마트컨트렉트 함수이름 중복 호출
- 스마트 컨트렉트 함수이름 중복
- 티스토리챌린지
- 러스트 기초
- ethers typescript
- chainlink 설명
- 스마트컨트렉트테스트
- rust 기초
- ambiguous function description
- 체인의정석
- 컨트렉트 배포 자동화
- ethers type
- git rebase
- SBT표준
- Vue.js
- 러스트기초
- ethers v6
- nest.js설명
- ethers websocket
- 스마트컨트렉트프록시
- 오블완
- vue기초
- 프록시배포구조
- multicall
- ethers
- Vue
- 컨트렉트 동일한 함수이름 호출
- 머신러닝기초
- 스마트컨트렉트 예약어 함수이름 중복
- Today
- Total
체인의정석
운영용 멀티시그 지갑 선택하기 & 멀티시그 지갑 테스트 및 사용을 위해 ethers.js로 encode된 data 만들기 본문
운영용 멀티시그 지갑 선택하기 & 멀티시그 지갑 테스트 및 사용을 위해 ethers.js로 encode된 data 만들기
체인의정석 2022. 5. 12. 14:21현재 gnosis의 멀티시그 지갑을 0.5.0 버전으로 업데이트하여 사용하기로 한 후 테스트 중이다.
consensys의 멀티시그 지갑을 2년반전에 사용했었는데 같은 프로그래머가 gnosis의 멀티시그 지갑을 만들었고 현재는 gnosisSafe를 사용하고 있다.
gnosis safe는 툴이 생각보다 잘 지원된다. 개발자용 배포툴도 있지만, 다중 체인을 지원하기에는 무리가 있다. 따라서 이건 패스!
또한 gnosisSafe의 경우 일반 유저를 대상으로 한 nft나 디파이, 표준 지키기, 가스토큰 처리,오프체인 처리 , 확장 모듈 등에 초점이 맞추어져있어 시스템운영에서의 멀티시그로는 적합하지 않다는 판단을 내렸다.
예전부터 참고되는 널리 사용되는 멀티시그 지갑은 아래와 같다.
→ 구버전 gnosis 멀티시그 지갑
https://github.com/gnosis/MultiSigWallet/blob/master/contracts/MultiSigWallet.sol
→ Consensys의 멀티시그 지갑 https://github.com/ConsenSysMesh/MultiSigWallet/blob/master/MultiSigWalletWithDailyLimit.sol
같은 사람이 코드를 작성한것으로 되어 있는데 컨센시스 소속인거 같다. 믿음직스럽다.
컨트렉트도 하나라서 그냥 리믹스에 넣고 테스트 하기에도 좋다.
오픈제플린 소속 개발자가 만든 코드도 찾을 수 있었다. 검증되어 오픈되고 사용되는 코드이다.
https://etherscan.io/address/0xba2906b18b069b40c6d2cafd392e76ad479b1b53#code
https://etherscan.io/txs?a=0xba2906b18b069b40c6d2cafd392e76ad479b1b53&f=3
여기서 자주 사용되는 함수들을 볼 수있다.
테스트 코드 작성하기
예전 web3에서 멀티시그 지갑을 사용한 경험을 바탕으로 abi.encdoe를 통해서 encoded된 데이터를 받아오기로 생각하고 검색하엿다. 아래 예시처럼 데이터를 encode 해오고 이를 멀티시그 지갑에 변수로 넣어서 제출 한 후 승인을 받은 후 실행 시키고 결과값을 확인하는 테스트 코드를 작성해 보려고 한다.
https://docs.ethers.io/v5/api/utils/abi/coder/#AbiCoder-encode
테스트 코드 작성에는 시간이 오래 걸리니 일단 리믹스 환경에서 임시로 토큰 하나를 배포해보고 전송이 잘 되나 확인할 예정이다.
그리고 evm계열 다른 체인의 적용 여부도 크게 상관없다는 결론이 나왓다. gas가 명시된 부분이 있긴하지만 이는 evm의 기본 전송 gas로 영향을 받는 체인은 없을것이다. 최소 가스의 경우 트랜잭션이 실패할경우 반환되기 때문에 바이트코드 레벨에서 컨트렉트 소스코드로 구현이 되어 있다.
일단 함수의 경우 abi를 사용해서 encode를 시키면 된다. 아래 예시를 찾아서 적용하였다.
https://github.com/ethers-io/ethers.js/issues/211
var abi = [ { name: 'foo', type: 'function', inputs: [ { type: 'uint256' } ], outputs: [ { type: 'uint8' }] } ];
var iface = new ethers.Interface(abi)
// Example
var calldata = iface.functions.foo.encode(42);
// "0x2fbebd38000000000000000000000000000000000000000000000000000000000000002a"
// Parsing call response
var response = "0x000000000000000000000000000000000000000000000000000000000000002b";
var result = iface.functions.foo.decode(response);
// 43
테스트 코드에서는 abi는 따로 모듈화를 시킨 ts 파일에서 빼와서 사용하고 기존에 일반 사인으로 된 부분을 abi를 이용해 encode 시킨후 보내버릴 예정이다. 인터페이스에 대한 abi를 가져와서 사용하면 위의 소스코드 처럼 사용할 수 있다. 지금은 모두 contractFactory로 컨트렉트 클래스가 있으니 거기서 바로 아래와같이 대입해서 encode시키려고 한다.
const encodedData = contractName.functionName.encode(input);
const transactionId = await multiSigContract.connect(singer).submitTransaction(encodedData);
근데 안되어서 예제대로 해보기로 하였다. 예제도 오류가 난다. 확인해본 결과
In v4, it has been moved to ethers.utils.Interface. That should fix that problem. :)
v4 버전의 문법대로 하려면 코드가 업데이트 되어야 한다고 한다.
var abi = [ { name: 'foo', type: 'function', inputs: [ { type: 'uint256' } ], outputs: [ { type: 'uint8' }] } ];
var iface = new ethers.utils.Interface(abi)
// Example
var calldata = iface.functions.foo.encode(42);
// "0x2fbebd38000000000000000000000000000000000000000000000000000000000000002a"
// Parsing call response
var response = "0x000000000000000000000000000000000000000000000000000000000000002b";
var result = iface.functions.foo.decode(response);
// 43
근데 이젠 또 v5라서 문법이 한번 더 바뀌었다고 한다.
In v5, Interface is no longer a meta-class, which should make interacting with it much easier, but will require your code to change.
See: https://docs.ethers.io/v5/api/utils/abi/interface/
So, for example, to encode function data, you now use:
const abi = [
"function transfer(address to, uint value)"
];
const iface = new Interface(abi);
const data = iface.encodeFunctionData("transfer", (someAddress, someValue));
You can also now perform encoding and decoding of both data and results (in v4, you could only encode data and only decode results).
근데 안되어서 값을 보니 값은 배열 형태로 들어가야 한다고 한다.
const abi = [
"function transfer(address to, uint value)"
];
const iface = new Interface(abi);
const data = iface.encodeFunctionData("transfer", [someAddress, someValue]);
이런식으로 배열을 잡으니 잘 되었다.
사실 data를 인코딩 하는 부분은 멀티 시그 지갑이 아니면 사용할 일이 없어서 생소했지만, 결국 어떤 기능이 필요한지 파악하고 현재 사용하는 해당 모듈의 버전에 맞게 예제를 수정해주면 되는거 같다.
어떻게든 예제 하나만 찾아서 뚫어봐야지..
아무튼 이렇게 abi encode 된걸 멀티시그의 data칸 안에 넣으면 나머지는 일반 적인 테스트 코드 작성할때 처럼 풀어서 사용하면 될 것이다.
그리고 테스트 중에 하나 더 발견했다.
chai에서 배열을 비교할때는
to.equal이 아닌 to.deep.equal을 사용해야 한다고 한다.
https://stackoverflow.com/questions/17526805/chai-test-array-equality-doesnt-work-as-expected
배열의 경우 단순 비교가 아니라 자료형이기 때문인거 같다.
이것도 익숙해져놔야 할거 같아서 일단 기록해두겠다.
'블록체인 > Solidity' 카테고리의 다른 글
Solidity에서 bytes와 bytes32의 유즈케이스 및 활용 문법 (0) | 2022.05.18 |
---|---|
논문에 사용하는 컨트렉트 구조 및 스마트컨트렉트 0.8 버전으로 구현한 주요 구문 정리 (Travel Rule Solution Example.sol) (0) | 2022.05.15 |
Solidity) internal 트랜잭션에 대한 이벤트 로그 테스트하기 (0) | 2022.04.20 |
경쟁사 스마트컨트렉트 분석하는법, 컨트렉트에 사용된 함수 이름 파악하기 (0) | 2022.03.23 |
스마트 컨트렉트 프록시 구조 - 세번째 패턴) Upgradeability using Inherited Storage (0) | 2022.03.18 |