Sure drop just drop the link here. I will have a look
Hi @Bhujanga
Here you go, This is the Github Link:
https://github.com/Suveett/CryptoKitties.git
Please download the CryptoKittiesUpgradeable.zip file(which contains the Proxy.sol, Storage.sol, Kittycontract.sol and KittycontractUpdated.sol) and not the CryptoKitties.zip file (This is the normal Project)
I have done the Unit testing in the deployer only (although its not recommended, but Honestly i also couldnât figure out how to implement a Unit testing on a Kittycontract through a Proxy Interaction without deploying ? )
But now, all the Tests are actually working Fine, thats my biggest relief, Just have a look if you can add some points and make this project Better and more Knowledgeable / Informative for me as well as you, perhaps. Or Kindly enlighten me if I have absolutely followed the wrong approach and maybe I should have followed a Newer better approach
Also, I am not so strong in JS, so somehow (inspite of several trials), my Kitties are not showing on my Marketplace.html page and catalogue.html page ( and the funny part is that the Console is showing No errors also, so maybe its a matter of visibility and not functionality - which i am unable to figure out- So Please help me if you can while you scroll through the Project).
On the Blockchain side (in solidity), everything is working/ compiling well.
One More thing I have not been able to understand yet is that while my Truffle shows only 4 deployments as I had intended - migrations, ArrayUtils, Kittycontract and Proxy), my Ganache shows 5 deployments (including the KittycontractUpdated.sol )
Can you shed some light on this ?
But since migrate --reset , My Ganache has hibernated and non -responsive .
Maybe this Project is not supposed to be done on ganache ?? I am just curious to learn More.
Please enlighten me
Thanks a ton in advance and Best Regards
Suveett Kalra
P.S. - Also, please leave your number (whatsapp), or your telegram name or discord name. This is the only way i can ask Tarun to get in touch with you
Cheers
I stoped using ganache GUI for the same reason, some times it goes buggy, it close it self, stop responding, so i have tried ganache CLI, which is through a command line, also truffle develop
creates an instance of a local blockchain, or hardhat node
does the same trick.
Carlos Z
Hi @Mariano_Collarte , I donât see how this resolves your original concern? I like your suggestion of resetting _initialized
in upgrade()
.
In my opinion, calling the initialize function a second time from the proxy (i.e. after another update of the functional contract) would be reverted because the _initialized
variable of the proxy has already been set to true after the first contract update and is never reset to false. Thus the statement require(!_initialized);
in the initialize function would fail, wouldnât it?
@dan-i or @thecil, could you please elaborate on that?
Iâve already looked at the link @dan-i shared with @Michal_Kosior on the same question: https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#the-constructor-caveat
My concern still exists. Am I missing something?
Please refer to this blog post which explains how storage collision can occur.
The crux of the potential issues is due to how EVM stores state:
- Storage layout for state variables begin at position 0 and increments for each new state variable. So the first state variable is stored at position 0, the second state variable is stored at position 1, the third stored at position 2, etc.
- Each struct or array element uses the next storage position, as if each one was defined separately on its own.
Therefore, I donât think youâll see an issue with your example as the second state variable, test
, is written to slot 1 and numDogs
state variable which exists in both contracts is unaffected at slot 0.
Although I havenât tested this, I think you may run into trouble if your new Functional Contract defined a new address state variable, testAddress
and the Functional Contactâs revised setNumDogs()
function called by delegatecall
also updated testAddress
to, say, the msg.sender
.
Since only _currentAddress
variable of address
type exists in the Proxy and the Proxy scope is used during delegatecall
, then the _currentAddress
variable declared inside Proxy would be updated to be the msg.sender
and the testAddress
would remain unaltered.
Hey Jon,
Thank you for your explanation, I really appreciate it,
Iâl read it later the blog post you refer.
Hi @Bhujanga
Could you find the time to go through my Contracts ?
Also, did Tarun get in ouch with you ??
Thanks and Regards
Suveett Kalra
Hi @filip Could you please take a look and comment on this issue? The question has come up a few times already but has not been answered clearly yet imo.
I followed Fillipâs instruction: npm install - g [email protected]
Iâm at a complete loss. I will say that I have encountered so many problems with the courses that use the PowerShell, which include this one and the previous version of ETH Smart Contract 201 before the new one replaced it.
Hi! I have a problem with the fallback function in the Proxy contract.
Proxy.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
import './Storage.sol';
contract Proxy is Storage{
address currentAddress;
constructor(address _curretsAddress){
currentAddress = _curretsAddress;
}
function upgrade(address _newAddress) public{
currentAddress = _newAddress;
}
//FALLBACK FUNCTION.
fallback() external{
//redirect ot currentAddress
address implementation = currentAddress;
require(currentAddress != address(0));
bytes memory data = msg.data;
assembly{
let result := delegatecall(gas(), implementation, add(data, 0x20), mload(data), 0, 0)
let size := returndatasize()
let ptr := mload(0x40)
returndatacopy(ptr, 0, size)
switch result
case 0 {revert(ptr, size)}
default{return(ptr, size)}
}
}//if someone makes a call to function that doen´t exist.
}
I get this error:
Hi @RBeato,
If you try your code along with receive()
, maybe it wonât throw an error.
For reference, check out my code -
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import './Storage.sol';
contract Proxy is Storage{
address currentAddress;
constructor(address _address){
currentAddress = _address;
}
function upgrade(address _address) public {
currentAddress = _address;
}
receive() payable external{}
fallback() external{
address implementation = currentAddress;
require(currentAddress != address(0),"Contract address is zero");
bytes memory data = msg.data;
assembly{
let result := delegatecall(gas(),implementation,add(data,0x20),mload(data),0,0)
let size := returndatasize()
let ptr := mload(0x40)
returndatacopy(ptr,0,size)
switch result
case 0 {revert(ptr,size)}
default {return(ptr,size)}
}
}
}
This is working fine on my machine
hey @RBeato,
I tried your code and got it to work.
If you still wanna run the same code without receive()
then try to change the solc version in truffle-config.js. something like below-
compilers: {
solc: {
version: "0.8.0",
I forgot to set the solc version. Thank you!
Regarding the A Better Way to Upgrade video, in solidity 0.8.0, (or after 0.6.0) one should mark the Dogs.sol
functions with virtual
to be able to override
them in
DogsUpdated.sol
.
You donât have to do that, because number of functions remain the same, you still can access the same functions (even though they are a bit changed). You need however to do proxy.upgrade() when you add some new function.
why am I having this why migrating my contractsâŚ
pls i want to post my code everything was done correctly yet i am still not able to migrate itâŚpls help me review it so i can make the corrections.thanks.
PhaxProxy.sol
//SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
import "./Storage.sol";
contract PhaxProxy is Storage {
address currentAddress;
constructor(address _currentAddress) public {
currentAddress = _currentAddress;
}
function upgrade(address _newAddress) public {
currentAddress = _newAddress;
}
fallback () payable external {
//redirect to currentaddress
address implementation = currentAddress;
require(currentAddress != address(0));
bytes memory data = msg.data;
assembly {
let result := delegatecall(gas(), implementation, add(data, 0x20), mload(data), 0, 0)
let size := returndatasize()
let ptr := mload(0x40)
returndatacopy(ptr, 0, size)
switch result
case 0 {revert(ptr, size)}
default {return(ptr, size)}
}
/*assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}*/
}
}
PhaxSwap.sol
//SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
import "./Storage.sol";
contract PhaxSwap is Storage {
modifier onlyOwner{
require(msg.sender == owner);
_;
}
constructor(){
owner = msg.sender;
}
function setMeatShop(uint256 toSet) public onlyOwner {
_uintStorage["Meat"] = toSet;
}
function getMeatShop() public view returns(uint256) {
return _uintStorage["Meat"];
}
}
PhaxSwap2.sol
//SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
import "./Storage.sol";
contract PhaxSwapUpgraded is Storage {
modifier onlyOwner{
require(msg.sender == owner);
_;
}
constructor() public {
initailized(msg.sender);
}
function initailized(address _owner) public {
require(!_initialized);
owner =_owner;
_initialized = true;
}
function setMeatShop(uint256 toSet) public onlyOwner {
_uintStorage["Meat"] = toSet;
}
function getMeatShop() public view returns(uint256) {
return _uintStorage["Meat"];
}
}
Storage.sol
//SPDX-License-Identifier: MIT
pragma solidity >0.8.0;
contract Storage {
mapping (string => uint256) _uintStorage;
mapping (string => address) _addressStorage;
mapping (string => bool) _boolStorage;
mapping (string => string) _stringStorage;
mapping (string => bytes4) _bytesStorage;
address public owner;
bool public _initialized;
}
migration file
const PhaxSwap = artifacts.require("PhaxSwap");
const PhaxSwapUpgraded = artifacts.require(" PhaxSwapUpgraded");
const PhaxProxy = artifacts.require("PhaxProxy");
module.exports = async function (deployer, network, accounts) {
const swap = await PhaxSwap.new();
const phax = await PhaxProxy.new(swap.address);
//create proxy meatt to fool truffle
var proxyMeat = await PhaxSwap.at(phax.address);
//set the number of meat through the proxy
await proxyMeat.setMeatShop(10);
//tested
var nrofMeatShop = await proxyMeat.getMeatShop();
console.log("Before Ugrade :" + nrofMeatShop.toNumber());
//new version of contract to deploy
const swap2 =await PhaxSwapUpgraded.new();
proxy.upgrade(PhaxSwapUpgraded.address);
proxyMeat = await PhaxSwapUpgraded.at(phax.address);
proxyMeat.initialized(accounts[0]);
nrofMeatShop = await proxyMeat.getMeatShop();
console.log( "After upgrade :" + nrofMeatShop.toNumber());
//set the number of meat through the proxy
await proxyMeat.setMeatShop(30);
}
errors while migrating:
_PhaxFiles_migration.js
========================
C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\459.bundled.js:26375
throw new Error("Could not find artifacts for " + import_path + " from any sources");
^
Error: Could not find artifacts for PhaxSwapUpgraded from any sources
at Resolver.require (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\resolver\dist\lib\resolver.js:61:1)
at Object.require (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:172:1)
at ResolverIntercept.require (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\ResolverIntercept.js:22:1)
at C:\Users\HP\Desktop\upgradable\migrations\2_PhaxFiles_migration.js:2:36
at Script.runInContext (vm.js:144:12)
at Script.runInNewContext (vm.js:149:17)
at Object.file (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\require\require.js:94:1)
at Migration._load (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:49:1)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at Migration.run (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\Migration.js:218:1)
at Object.runMigrations (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:150:1)
at Object.runFrom (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\migrate\index.js:110:1)
at runMigrations (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:258:1)
at Object.run (C:\Users\HP\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\commands\migrate.js:223:1)
- Fetching solc version list from solc-bin. Attempt #1
- Fetching solc version list from solc-bin. Attempt #1
- Blocks: 0 Seconds: 0
- Saving migration to chain.
pls help me check properly and teach me what i am not doing right
Guys just FYI
with latest solidity we donât use function keyword
instead of using
function() payable external {}
Use
fallback() payable external {}
See release of 0.6.0 https://solidity.readthedocs.io/en/v0.7.4/060-breaking-changes.html#semantic-and-syntactic-changes
Had to give it another read myself, you beat me to the post! Happy Hacking.
Ok tying to compile in pragma solidity 0.8.6;
using a fallback()
keyword but getting an error where doing same code in pragma solidity 0.5.2;
using funciton()
keyword it compiles correctly. Hereâs my code and error, was trying to google it but cant find answers:
pragma solidity 0.8.6;
import "./Storage.sol";
contract Proxy is Storage {
address currentAddress;
constructor(address _currentAddress) public {
currentAddress = _currentAddress;
}
function upgrade(address _newAddress) public {
currentAddress = _newAddress;
}
fallback() payable external {
address implementation = currentAddress;
require(currentAddress != address(0));
bytes memory data = msg.data;
assembly {
let result := delegatecall(gas, implementation, add(data, 0x20), mload(data), 0, 0)
let size := returndatasize
let ptr := mload(0x40)
returndatacopy(ptr, 0, size)
switch result
case 0 {revert(ptr, size)}
default {return(ptr, size)}
}
}
}
C:\Users\kamil\Documents\Ethereum-201\Proxy>truffle compile
Compiling your contracts...
===========================
> Compiling .\contracts\Dogs.sol
> Compiling .\contracts\Proxy.sol
> Compiling .\contracts\Storage.sol
> Compiling .\contracts\Storage.sol
> Compilation warnings encountered:
Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment
containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
--> /C/Users/kamil/Documents/Ethereum-201/Proxy/contracts/Dogs.sol
,Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
--> /C/Users/kamil/Documents/Ethereum-201/Proxy/contracts/Storage.sol
ParserError: Builtin function "gas" must be called.
--> /C/Users/kamil/Documents/Ethereum-201/Proxy/contracts/Proxy.sol:23:40:
|
23 | let result := delegatecall(gas, implementation, add(data, 0x20), mload(data), 0, 0)
| ^^^
Compilation failed. See above.
Truffle v5.3.7 (core: 5.3.7)
Node v16.2.0
C:\Users\kamil\Documents\Ethereum-201\Proxy>
seem to be more changes in newer version. Should will be aware of that?
many thanks
Kamil