We want to implement a classic MyToken contract that that inherits from Erc20 and change it's behavior by overriding the implementation of update(..) virtual method from Erc20.
Erc20 is implemented with OpenZeppelin code as reference (link here)
Solidity way:
abstract contract ERC20 {
//.....
function _update(address from, address to, uint256 value) internal virtual {
// function body
}
//other Erc20 functions
}
contract MyToken is ERC20, Pausable {
constructor {...}
function _update(address from, address to, uint256 value) internal virtual override {
// new logic goes here
// after new logic is executed we want to run base impl from ERC20
super._update(from, to, value);
}
}
To do the same with Stylus following structure hierarchy was defined:
sol_storage! {
pub struct Erc20<T> {
// here goes the erc20 fields
}
}
impl<T: Erc20Params> Erc20<T> {
pub fn update(&mut self, from: Address, to: Address, value: U256) -> Result<(), Vec<u8>> {
// method body
}
}
#[external]
impl<T: Erc20Params> Erc20<T> {
pub fn transfer(&mut self, to: Address, value: U256) -> Result<bool, Erc20Error> {
let owner = msg::sender();
self.transfer_internal(owner, to, value)?;
Ok(true)
}
fn transfer_internal(&mut self, from: Address, to: Address, value: U256) -> Result<(), Erc20Error> {
if from == Address::ZERO {
return Err(Erc20Error::Erc20InvalidSpender(Erc20InvalidSpender {
spender: Address::ZERO,
}));
}
if to == Address::ZERO {
return Err(Erc20Error::Erc20InvalidReceiver(Erc20InvalidReceiver {
receiver: Address::ZERO,
}));
}
self.update(from, to, value)
}
// other methods of Erc20
}
-------------- MyToken impl
sol_storage! {
#[entrypoint]
pub struct MyToken {
#[borrow]
Erc20<MyTokenParams> erc20;
}
}
impl MyToken {
pub fn update(&mut self, from: Address, to: Address, value: U256) -> Result<(), Vec<u8>> {
// new logic comes here
self.erc20.update(from, to, value)?;
Ok(())
}
}
#[external]
#[inherit(Erc20<MyTokenParams>)]
impl MyToken {
// body if MyToken
}
Issue
Expected behavior: when Erc20 methods call self.update(..) like in example above in transfer_internal(..) method, execution goes to overridden function defined in MyToken impl
Current behavior: calling self.update(..) inside transfer_internal(..) executes the update(..) from Erc20 impl
Stylus version:
0.4.2
Class structure:
We want to implement a classic MyToken contract that that inherits from
Erc20
and change it's behavior by overriding the implementation ofupdate(..)
virtual method fromErc20
.Erc20
is implemented with OpenZeppelin code as reference (link here)Solidity way:
To do the same with Stylus following structure hierarchy was defined:
Issue
Expected behavior: when Erc20 methods call self.update(..) like in example above in
transfer_internal(..)
method, execution goes to overridden function defined inMyToken impl
Current behavior: calling
self.update(..)
insidetransfer_internal(..)
executes theupdate(..)
fromErc20 impl