일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- nest.js설명
- ethers type
- SBT표준
- ethers typescript
- 깃허브명령어
- ambiguous function description
- git rebase
- 프록시배포구조
- 스마트 컨트렉트 함수이름 중복
- ethers websocket
- 러스트 기초
- Vue.js
- 스마트컨트렉트 예약어 함수이름 중복
- 러스트기초
- 스마트컨트렉트프록시
- 머신러닝기초
- Vue
- 컨트렉트 동일한 함수이름 호출
- vue기초
- 컨트렉트 배포 자동화
- 스마트컨트렉트 함수이름 중복 호출
- multicall
- chainlink 설명
- 스마트컨트렉트테스트
- 체인의정석
- ethers v6
- ethers
- 러스트 기초 학습
- rust 기초
- nestjs 튜토리얼
- Today
- Total
체인의정석
delegateCall에서의 상태변화 가능여부 및 사용하면 안되는 이유 본문
delegateCall에 대한 함수를 작성했는데 hardhat에서는 테스트 코드가 오류가 나는 상황
문제가 없는거 같아 같은 코드를 remix에서 작성했는데 에러가 발생하지 않았다.
알 수 없는 오류가 발생했으니 하드햇에 보고라는 메세지가 떴다.
=> Hardhat의 경우 아직 delegateCall을 제대로 테스트 할 경우 오류가 날 수 있으므로 주의
TestDelegate 컨트렉트
pragma solidity >=0.7.0 <0.9.0;
contract TestDelegate {
bool public check;
function testDelegateCall(uint256 _value) public returns(uint256) {
check=true;
return _value;
}
}
TestDelegateCaller 컨트렉트
pragma solidity >=0.7.0 <0.9.0;
// import "@openzeppelin/contracts/access/Ownable.sol";
contract TestDelegateCaller {
uint256 public result;
bool public checked;
function doDelegateCall(address _delegate, uint256 _value) public returns(uint256) {
(bool check, bytes memory data) = address(_delegate).delegatecall(abi.encodeWithSignature("testDelegateCall(uint256)",_value));
(uint256 tokenId) = abi.decode(data, (uint256));
result = tokenId;
checked = check;
return tokenId;
}
}
테스트 코드
import { expect } from "chai";
import { ethers } from "hardhat";
import { Contract } from "ethers";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
// let exchange: Contract;
let DelegateCall: Contract;
let DelegateCaller: Contract;
let signerOwner: SignerWithAddress;
describe("Start Delegate Call test", async function () {
it("initialize signer", async function () {
const signers = await ethers.getSigners();
signerOwner = signers[0];
console.log("signerOwner", signerOwner.address);
});
it("should deploy DelegateCall contract correctly", async function () {
const DelegateCallFactory = await ethers.getContractFactory("TestDelegate");
DelegateCall = await DelegateCallFactory.deploy();
await DelegateCall.deployed();
});
it("should deploy DelegateCaller contract correctly", async function () {
const DelegateCallerFactory = await ethers.getContractFactory(
"TestDelegateCaller"
);
DelegateCaller = await DelegateCallerFactory.deploy();
await DelegateCaller.deployed();
});
it("do delegate call testing", async function () {
const delegateCallTx = await DelegateCaller.doDelegateCall(
DelegateCaller.address,
1
);
const result = await delegateCallTx.wait();
console.log(result);
expect(await DelegateCaller.result()).to.equal(1);
await expect(DelegateCaller.checked()).to.be.true;
});
});
테스트로 배포한 코드 1이 delegate 함수 호출하는 delegateCaller 컨트렉트
https://rinkeby.etherscan.io/address/0x9f9de9156d39aabc758b47f6e038724b8152f15e#code
테스트로 배포한 코드 2가 호출 되는 delegate 함수가 있는 testDelegate 컨트렉트
https://rinkeby.etherscan.io/address/0x7c1cd789f73d8a58227c640082c7ce87f8f5bc06#code
이더스캔에서는 Delegatecall 실행을 막아놔서 Remix에서 실행해 보았다.
https://rinkeby.etherscan.io/address/0xb0c10422be9a962a1dd4ec5d01a2667db7de4d1f
확인 결과 인터널 트랜잭션도 다 찍혔고 바뀐 결과값이 리턴되었지만
Call의 대상이 되는 컨트렉트에서 찍히는 값은 바뀜이 없었다.
=> 결론
delegateCall을 통해 함수를 호출할 경우 에러가 나지는 않고 값을 리턴 받을 경우 상태변화는 일어나지 않는다.
여기에 대해 학회장님에게 피드백을 받았는데
delegateCall이 슬롯을 변경시켜서 메모리 영역에서 계산하고 끝나는게 아니고 영구적으로 바뀌는 부분때문에 외부인한테 노출이 안되어도 자체적으로 보안에 취약해진다고 한다.
delegateCall의 경우 다른 컨트렉트에서 로직을 가져와서 실행시킨 컨트렉트에서 실행하는거라 상태변화가 안되는게 맞다고 확인을 받았다.
이걸 안정적으로 시켜주는 부분이 있는데 찾아보려면 다이아몬드 스토리지나 UUIP를 알아봐야 된다고 한다.
'블록체인 > Solidity' 카테고리의 다른 글
Solidity에서 자주 만나는 에러 "CompilerError: Stack too deep, try removing local variables." 그리고 에러에 대한 해결 방안 정리 , 이벤트 로그와 함수 입력값 구조체로 개수 줄이기 (0) | 2022.07.13 |
---|---|
이벤트 로그에 구조체 데이터 넣기, 이벤트 로그 작성하기 (0) | 2022.07.13 |
DelegateCall에서 값을 가져오는 케이스 (0) | 2022.07.08 |
하나의 컨트렉트를 여러개로 분리해서 만들 때의 주의 사항 (0) | 2022.07.07 |
Warning: Return value of low-level calls not used (0) | 2022.07.06 |