# Solidity delegatecall vs. Yul delegatecall

**URL:** <https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496>\
**Category:** Support\
**Created:** [November 9, 2020, 2:59pm UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496 "2020-11-09T14:59:36Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![cjd9s](https://avatars.discourse-cdn.com/v4/letter/c/b9e5f3/32.png) [@cjd9s](https://forum.openzeppelin.com/u/cjd9s)\
**Post date:** [November 9, 2020, 2:59pm UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496/1 "2020-11-09T14:59:36Z")

</div>

Hi Andrew @abcoathup,

I trust that you are well.

According to the OpenZeppelin explanation of proxy contracts ([https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies)), Yul assembly code needs to be used for the following reason:

> The technique needs to be implemented using Yul because Solidity’s `delegatecall` returns a boolean instead of the callee’s return data.

```solidity
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) }
}

```

However, delegatecall as a member of the address type returns a success condition boolean and return data. ([https://solidity.readthedocs.io/en/v0.7.4/units-and-global-variables.html#index-6](https://solidity.readthedocs.io/en/v0.7.4/units-and-global-variables.html#index-6))

> .delegatecall(bytes memory) returns (bool, bytes memory) issue low-level DELEGATECALL with the given payload, returns success condition and return data, forwards all available gas, adjustable

What am I missing? Cheers.

Sincerely,  
Craig

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [November 16, 2020, 4:54am UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496/2 "2020-11-16T04:54:10Z")

</div>

Hi @cjd9s,

Sorry for the delay in responding. I will have to find out why this is.

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [November 23, 2020, 1:18am UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496/3 "2020-11-23T01:18:22Z")

</div>

Hi @cjd9s,

I am still working on my understanding of this and will come back to you.

---

<div class="post-metadata">

**Author:** ![cjd9s](https://avatars.discourse-cdn.com/v4/letter/c/b9e5f3/32.png) [@cjd9s](https://forum.openzeppelin.com/u/cjd9s)\
**Post date:** [November 23, 2020, 4:18pm UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496/4 "2020-11-23T16:18:35Z")

</div>

Hi Andrew @abcoathup,

Much appreciated. Cheers.

Sincerely,  
Craig

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [November 25, 2020, 1:52am UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496/5 "2020-11-25T01:52:23Z")

</div>

Hi @cjd9s,

Since Solidity 0.5, `delegatecall` provides access to the return data:

> **[Solidity v0.5.0 Breaking Changes — Solidity 0.7.5 documentation](https://docs.soliditylang.org/en/v0.7.5/050-breaking-changes.html?highlight=delegatecall#semantic-and-syntactic-changes)**

The proxy was written prior to Solidity 0.5.

Some assembly is still required as the fallback function can’t have a return value, so Solidity won’t allow us to return anything.

The proxy could potentially be changed to only use assembly for the return statement. Using assembly for the entire block may be cheaper but the gas costs haven’t been measured.

---

<div class="post-metadata">

**Author:** ![cjd9s](https://avatars.discourse-cdn.com/v4/letter/c/b9e5f3/32.png) [@cjd9s](https://forum.openzeppelin.com/u/cjd9s)\
**Post date:** [November 25, 2020, 1:40pm UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496/6 "2020-11-25T13:40:33Z")

</div>

Hi Andrew @abcoathup,

Excellent answer. Makes perfect sense. Cheers.

Sincerely,  
Craig

---

<div class="post-metadata">

**Author:** ![PaulRBerg](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/paulrberg/32/14286_2.png) [@PaulRBerg](https://forum.openzeppelin.com/u/PaulRBerg)\
**Post date:** [August 30, 2021, 3:40pm UTC](https://forum.openzeppelin.com/t/solidity-delegatecall-vs-yul-delegatecall/4496/7 "2021-08-30T15:40:03Z")

</div>

> [@abcoathup](#):
>
> the fallback function can’t have a return value

I don't think that this is the case anymore. As per the [docs](https://docs.soliditylang.org/en/v0.8.7/contracts.html#fallback-function) for Solidity v0.8.7:

> A contract can have at most one `fallback` function, declared using either
> 
> - `fallback () external [payable]` or
> - `fallback (bytes calldata _input) external [payable] returns (bytes memory _output)`

It is however true that the [receive](https://docs.soliditylang.org/en/v0.8.7/contracts.html#receive-ether-function) ether function can't have a return type. And since `receive` is [used](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.1/contracts/proxy/Proxy.sol#L70-L76) in OpenZeppelin's `Proxy.sol`, assembly is still required.

At any rate, I would love to see the `_delegate` implementation use assembly only for the return statement. The Solidity-level `delegatecall` is much more palatable.
