Different proxy code to upgrade smart contract and reentrancy attacks
Oct 15 2020
I am trying to upgrade smart contract in ethereum. I found that proxy pattern can help me with this. In the openzeppelin docs, I should add the following code in fallback function in my contract:
assembly {
let ptr := mload(0x40)
// (1) copy incoming call data
calldatacopy(ptr, 0, calldatasize)
// (2) forward call to logic contract
let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
let size := returndatasize
// (3) retrieve return data
returndatacopy(ptr, 0, size)
// (4) forward return data back to caller
switch result
case 0 { revert(ptr, size) }
default { return(ptr, size) }
}
It seems that I should forward call and retrieve the return data. However, in some contracts, they just upgrade the contract with code like this:
/**
* Resolves asset implementation contract for the caller and forwards there transaction data,
* along with the value. This allows for proxy interface growth.
*/
function () payable {
_getAsset().__process.value(msg.value)(msg.data, msg.sender);
}
I have two questions:
- Can the second code also upgrade the smart contract?
- I think add the first code in
fallbackfunction in my contract can lead to reentrancy attack, is it true? Thanks!
Odpowiedzi
Ismael Oct 16 2020 at 22:59
They are two ways to make a contract upgradeable.
- Pierwsza używa kodu operacji DELEGATECALL. Nie zmienia to msg.sender. Musi użyć zestawu, aby odzyskać zwróconą wartość. Mają pewne ograniczenia, o których musisz wiedzieć przed ich użyciemhttps://blog.openzeppelin.com/the-transparent-proxy-pattern/, https://blog.openzeppelin.com/proxy-patterns/.
- Drugi używa zwykłego kodu operacji CALL. Zmienia msg.sender, więc kod musi się do tego dostosować. Nie obsługuje funkcji pobierających, ponieważ ignoruje zwracaną wartość.
Żadna opcja nie zapewnia ochrony przed atakami ponownego wejścia, zależy to od implementacji.