Skip to content

Commit

Permalink
fix(p2p/proxy_workshop): fix readme and contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas Leclerc committed Sep 2, 2024
1 parent ea0e944 commit 58f288b
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 201 deletions.
258 changes: 162 additions & 96 deletions p2p/6.Create_a_proxy/README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion p2p/6.Create_a_proxy/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Also, I recommand you to use the extension formatter. It will format your code o
{
"editor.formatOnSave": true,
"[solidity]": {
"editor.defaultFormatter": "JuanBlanco.solidity"
"editor.defaultFormatter": "NomicFoundation.hardhat-solidity"
}
}
```
Expand Down
16 changes: 6 additions & 10 deletions p2p/6.Create_a_proxy/help/fallback.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# 🙋‍♂️ Help to create the fallback function for the proxy
## Help to create the fallback function for the proxy

Check failure on line 1 in p2p/6.Create_a_proxy/help/fallback.md

View workflow job for this annotation

GitHub Actions / lint

First line in a file should be a top-level heading [Context: "## Help to create the fallback..."]

p2p/6.Create_a_proxy/help/fallback.md:1 MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "## Help to create the fallback..."]

The fallback function is a function that is called when a contract is called with a method that is not implemented. This function is called with the method name and the arguments that were passed to the proxy.

```solidity
fallback() external payable {
(bool success, bytes memory returnData) = implementation.delegatecall(msg.data);
(bool success, bytes memory returnData) = implem.delegatecall(msg.data);
if (!success) {
if (returnData.length > 0) {
assembly {
Expand All @@ -21,10 +21,10 @@ fallback() external payable {
}
```

## ⛓️‍💥 Let's break down the fallback function line by line:
### Let's break down the fallback function line by line:

1. `(bool success, bytes memory returnData) = implementation.delegatecall(msg.data);`
- This line calls the `delegatecall` function on the `implementation` contract with the `msg.data` that was sent to the proxy. The `delegatecall` function executes the code of the `implementation` contract in the context of the proxy contract. The `success` variable will be `true` if the `delegatecall` was successful, and the `returnData` variable will contain the return data from the `delegatecall`.
1. `(bool success, bytes memory returnData) = implemn.delegatecall(msg.data);`
- This line calls the `delegatecall` function on the implementation contract with the `msg.data` that was sent to the proxy. The `delegatecall` function executes the code of the implementation contract in the context of the proxy contract. The `success` variable will be `true` if the `delegatecall` was successful, and the `returnData` variable will contain the return data from the `delegatecall`.

2. `if (!success) {`
- This line checks if the `delegatecall` was successful. If it was not successful, the code inside the `if` block will be executed.
Expand All @@ -38,10 +38,6 @@ fallback() external payable {
4. `assembly { return(add(returnData, 32), mload(returnData)) }`
- This line returns the `returnData` if the `delegatecall` was successful. The `returnData` contains the return value of the function that was called in the `implementation` contract.

👌 Perfect now you have a fallback function that will call the `implementation` contract with the method name and arguments that were passed to the proxy.

If the `delegatecall` is successful, it will return the return value of the function that was called in the `implementation` contract. If the `delegatecall` fails, it will revert with the revert reason.
Perfect now you have a fallback function that will call the `implementation` contract with the method name and arguments that were passed to the proxy. If the `delegatecall` is successful, it will return the return value of the function that was called in the `implementation` contract. If the `delegatecall` fails, it will revert with the revert reason.

> ⚠️ It's the main logic of the proxy so if you have any questions feel free to ask to the PoC Team.
⏪ Back to the [Workshop](../README.md).
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

contract COUNTER_V1 {
contract CounterV1 {
uint256 public count;

constructor() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

contract COUNTER_V2 {
contract CounterV2 {
uint256 public _count;

constructor() {
Expand Down
30 changes: 30 additions & 0 deletions p2p/6.Create_a_proxy/utils/ProxyV1.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import "forge-std/Test.sol";
import "../src/proxys/ProxyV1.sol";
import "../src/implementations/CounterV1.sol";

contract ProxyTest is Test {
ProxyV1 public proxy_v1;
CounterV1 public counter;

function setUp() public {
counter = new CounterV1();
proxy_v1 = new ProxyV1(address(counter));
}

function testCounter() public {
assertEq(counter.total(), 0, "Counter should be 0");
counter.add();
assertEq(counter.total(), 1, "Counter should be 1");
}

function testProxy_v1() public {
uint256 total = CounterV1(address(proxy_v1)).total();
assertEq(total, 0, "total should be 0");
CounterV1(address(proxy_v1)).add();
total = CounterV1(address(proxy_v1)).total();
assertEq(total, 1, "total should be 1");
}
}
32 changes: 32 additions & 0 deletions p2p/6.Create_a_proxy/utils/ProxyV2.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import "forge-std/Test.sol";
import "../src/proxys/ProxyV2.sol";
import "../src/implementations/CounterV1.sol";
import "../src/implementations/CounterV2.sol";

contract ProxyTest is Test {
ProxyV2 public proxy_v2;
CounterV1 public counter;
CounterV2 public counter_v2;

function setUp() public {
counter = new CounterV1();
counter_v2 = new CounterV2();
proxy_v2 = new ProxyV2(address(counter));
}

function testProxy_v2() public {
uint256 total = CounterV1(address(proxy_v2)).total();
assertEq(total, 0, "total should be 0");
CounterV1(address(proxy_v2)).add();
total = CounterV1(address(proxy_v2)).total();
assertEq(total, 1, "total should be 1");
// change implementation
proxy_v2.setImplementation(address(counter_v2));
CounterV2(address(proxy_v2)).add(2);
total = CounterV2(address(proxy_v2)).total();
assertEq(total, 3, "total should be 3");
}
}
47 changes: 47 additions & 0 deletions p2p/6.Create_a_proxy/utils/ProxyV3.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import "forge-std/Test.sol";
import "../src/proxys/ProxyV1.sol";
import "../src/proxys/ProxyV2.sol";
import "../src/proxys/ProxyOwnableUpgradable.sol";
import "../src/implementations/CounterV1.sol";
import "../src/implementations/CounterV2.sol";

contract ProxyTest is Test {
CounterV1 public counter;
CounterV2 public counter_v2;
ProxyOwnableUpgradable public proxy_ownable_upgradable;
address public nonOwner;

function setUp() public {
counter = new CounterV1();
counter_v2 = new CounterV2();
proxy_ownable_upgradable = new ProxyOwnableUpgradable(address(counter));
nonOwner = address(0x1234);
}

function testProxyUpgrade() public {
CounterV1(address(proxy_ownable_upgradable)).add();
assertEq(CounterV1(address(proxy_ownable_upgradable)).total(), 1, "should be 1");
proxy_ownable_upgradable.upgradeTo(address(counter_v2));
assertEq(proxy_ownable_upgradable.getImplementation(), address(counter_v2), "implementation should be CounterV2");
assertEq(CounterV2(address(proxy_ownable_upgradable)).total(), 1, "total should be 1");
CounterV2(address(proxy_ownable_upgradable)).add(3);
assertEq(CounterV2(address(proxy_ownable_upgradable)).total(), 4, "total should be 4");
}

function testUpgradeToAsNonOwner() public {
// Attempt to upgrade implementation with a non-owner account
vm.prank(nonOwner);
vm.expectRevert("Caller is not the owner");
proxy_ownable_upgradable.upgradeTo(address(counter_v2));
assertEq(proxy_ownable_upgradable.getImplementation(), address(counter), "Implementation should not change for non-owner");
}

function testTransferProxyOwnership() public {
// Transfer ownership to nonOwner
proxy_ownable_upgradable.transferProxyOwnership(nonOwner);
assertEq(proxy_ownable_upgradable.getOwner(), nonOwner, "Owner should be nonOwner");
}
}
92 changes: 0 additions & 92 deletions p2p/6.Create_a_proxy/utils/proxy.t.sol

This file was deleted.

0 comments on commit 58f288b

Please sign in to comment.