Hey,
I’ve recently been going over my understanding of transparent proxies, and noticed that at some-point there’s been a change:
Old code from OZ blog post
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) }
}
New code from OZ contract:
assembly {
// (1) copy incoming call data
calldatacopy(0, 0, calldatasize())
// (2) forward call to logic contract
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// (3) retrieve return data
returndatacopy(0, 0, returndatasize())
// (4) forward return data back to caller
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
I know that let ptr := mload(0x40) used to be a special-slot containing the address of the next allocatable slot, so it made sense to me that it was used as the reference slot for some of these OPs, but now they use 0, is this some kind of shortcut which has been introduced? Or is there some assumption being made that 0 is the slot where the delegatcall will return its value?
P.S. This is a dupe from a post I made in security a few days ago, I now realise it should have been posted here - but I don’t appear to be able to delete my previous post.