I'm trying to use my custom ERC20 contract that is stored in my local storage in the SWAP project that I'm working on.
the error I'm getting while trying to use the erc20 import inside the SWAP contract:
unresolved import `erc20::Erc20`
no `Erc20` in the root
help: a similar name exists in the module: `erc20`rustc(E0432)
swap.rs(10, 9): no `Erc20` in the root
Here is how I import the erc20 module in SWAP.rs:
#![cfg_attr(not(feature = "std"), no_std)]
use ink_lang as ink;
#[ink::contract]
mod swapv1 {
#[cfg(not(feature = "ink-as-dependency"))]
use erc20::Erc20; <-----
use ink_env::call::FromAccountId;
use ink_prelude::string::String;
// snip....
This is how I import the ERC20 module inside SWAP.rs .toml file:
erc20 = { path = "../erc20/", version="3.0.0-rc4", default-features = false, features = ["ink-as-dependency"] }
I've also added the following configuration to the ERC20 .toml file:
crate-type = [
"rlib",
]
Here is the content of the ERC20 module file:
#![cfg_attr(not(feature = "std"), no_std)]
pub use self::erc20::Erc20;
use ink_lang as ink;
#[ink::contract]
pub mod erc20 {
#[cfg(not(feature = "ink-as-dependency"))]
use ink_prelude::string::String;
use ink_storage::traits::SpreadAllocate;
#[ink(storage)]
#[derive(SpreadAllocate)]
pub struct Erc20 {
/// Total token supply.
total_supply: Balance,
/// Mapping from owner to number of owned token.
balances: ink_storage::Mapping<AccountId, Balance>,
/// Mapping of the token amount which an account is allowed to withdraw
/// from another account.
allowances: ink_storage::Mapping<(AccountId, AccountId), Balance>,
/// Token name
name: String,
/// Token symbol (ticker)
symbol:String,
}
/// Event emitted when a token transfer occurs.
#[ink(event)]
pub struct Transfer {
#[ink(topic)]
from: Option<AccountId>,
#[ink(topic)]
to: Option<AccountId>,
value: Balance,
}
/// Event emitted when an approval occurs that `spender` is allowed to withdraw
/// up to the amount of `value` tokens from `owner`.
#[ink(event)]
pub struct Approval {
#[ink(topic)]
owner: AccountId,
#[ink(topic)]
spender: AccountId,
value: Balance,
}
/// The ERC-20 error types.
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
/// Returned if not enough balance to fulfill a request is available.
InsufficientBalance,
/// Returned if not enough allowance to fulfill a request is available.
InsufficientAllowance,
}
/// The ERC-20 result type.
pub type Result<T> = core::result::Result<T, Error>;
impl Erc20 {
/// Creates a new ERC-20 contract with the specified initial supply.
#[ink(constructor)]
pub fn new(name: String, symbol: String, initial_supply: Balance) -> Self {
let caller = Self::env().caller();
let me = ink_lang::utils::initialize_contract(|contract: &mut Self| {
contract.balances.insert(caller, &initial_supply);
contract.allowances.insert((caller,caller),&initial_supply);
contract.symbol = symbol;
contract.name = name;
});
Self::env().emit_event(Transfer {
from: None,
to: Some(caller),
value: initial_supply,
});
me
}
/// Returns the total token supply.
#[ink(message)]
pub fn total_supply(&self) -> Balance {
self.total_supply
}
/// Returns the account balance for the specified `owner`.
///
/// Returns `0` if the account is non-existent.
#[ink(message)]
pub fn balance_of(&self, owner: AccountId) -> Balance {
self.balances.get(&owner).unwrap_or(0)
}
/// Returns the amount which `spender` is still allowed to withdraw from `owner`.
///
/// Returns `0` if no allowance has been set `0`.
#[ink(message)]
pub fn allowance(&self, owner: AccountId, spender: AccountId) -> Balance {
self.allowances.get(&(owner, spender)).unwrap_or(0)
}
/// Transfers `value` amount of tokens from the caller's account to account `to`.
///
/// On success, a `Transfer` event is emitted.
///
/// # Errors
///
/// Returns `InsufficientBalance` error if there are not enough tokens on
/// the caller's account balance.
#[ink(message)]
pub fn transfer(&mut self, to: AccountId, value: Balance) -> Result<()> {
let from = self.env().caller();
self.transfer_from_to(from, to, value)
}
/// Allows `spender` to withdraw from the caller's account multiple times, up to
/// the `value` amount.
///
/// If this function is called again it overwrites the current allowance with `value`.
///
/// An `Approval` event is emitted.
#[ink(message)]
pub fn approve(&mut self, spender: AccountId, value: Balance) -> Result<()> {
let owner = self.env().caller();
self.allowances.insert((owner, spender), &value);
self.env().emit_event(Approval {
owner,
spender,
value,
});
Ok(())
}
/// Transfers `value` tokens on the behalf of `from` to the account `to`.
///
/// This can be used to allow a contract to transfer tokens on one's behalf and/or
/// to charge fees in sub-currencies, for example.
///
/// On success, a `Transfer` event is emitted.
///
/// # Errors
///
/// Returns `InsufficientAllowance` error if there are not enough tokens allowed
/// for the caller to withdraw from `from`.
///
/// Returns `InsufficientBalance` error if there are not enough tokens on
/// the the account balance of `from`.
#[ink(message)]
pub fn transfer_from(
&mut self,
from: AccountId,
to: AccountId,
value: Balance,
) -> Result<()> {
let caller = self.env().caller();
let allowance = self.allowance(from, caller);
if allowance < value {
return Err(Error::InsufficientAllowance)
}
self.transfer_from_to(from, to, value)?;
self.allowances.insert((from, caller), &(allowance - value));
Ok(())
}
/// Transfers `value` amount of tokens from the caller's account to account `to`.
///
/// On success, a `Transfer` event is emitted.
///
/// # Errors
///
/// Returns `InsufficientBalance` error if there are not enough tokens on
/// the caller's account balance.
fn transfer_from_to(
&mut self,
from: AccountId,
to: AccountId,
value: Balance,
) -> Result<()> {
let from_balance = self.balance_of(from);
if from_balance < value {
return Err(Error::InsufficientBalance)
}
self.balances.insert(from, &(from_balance - value));
let to_balance = self.balance_of(to);
self.balances.insert(to, &(to_balance + value));
self.env().emit_event(Transfer {
from: Some(from),
to: Some(to),
value,
});
Ok(())
}
}
/// The IERC20Metadata (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/IERC20Metadata.sol)
impl Erc20 {
/// Returns the token name.
#[ink(message)]
pub fn name(&self) -> String {
self.name.clone()
}
/// Returns the token name.
#[ink(message)]
pub fn symbol(&self) -> String {
self.symbol.clone()
}
/// Returns the decimal places of the token.
#[ink(message)]
pub fn decimals(&self) -> u8 {
18
}
}
}
Change
use erc20::Erc20;
to
use erc20::Erc20Ref;
Put this at the top of the ERC20 contract:
pub use self::erc20::{Erc20, Erc20Ref};
You can see an example of this in the subber contract where it specifies itself as
SubberRef
and is then called from the main delegator contract