Background
I have created a ERC20 smart contract(TF_Minting) which has a mapping that stores the information about how much token does an account address holds.
The mapping looks like this:
mapping (address => uint) public mintedTF
It is a pretty basic mapping with nothing special.
I have published the contract and it is now supposedly running live on testnet. Let's assume it is already fed with data and there is mapping of around 1000 addresses in it.
Problem
Now, I am creating a smart contract (TF_Reward) where I want to give some rewards to the addresses that hold my TF token. The reward system is respective to the amount that all individual addresses hold, so thus it is crucial for me to access the addresses data as well as the amount of TF they hold individually.
In short, I want to get access to the entire mapping of the TF_mint smart contract inside TF_Reward smart contract.
What is the best possible way to solve my issue? Can I create any interface or something?
Additional Information
The logic that I want to add in my TF_Reward smart contract is:
Check the Comment in the code
function _distributeClaim(
address _claimant,
uint256 _balances
) internal returns (bool){
uint256 payableAmount = tradingProfits * _balances / totalInvestedTFs;
require(
payableAmount < address(this).balance,
"TF: Insufficient Balance in Contract!"
);
////////Something here that works in such a manner that I substact the claimed balance from the available balance of that particular address so that it cannot claim the balance again and again.
(bool success, ) = payable(_claimant).call{ value: payableAmount }("");
return success;
}
If this function was in the same contract that has the original mapping, the added logic would have been something like:
mintedTF[_claimant] -= balance;
But I cannot add this line in the TF_Reward smart contract, since it does not have the original mapping along with it's data.
Summarize
How to access the mapping data of a smart contract in a different smart contract?
Accessing a state variable of another contract:
- Read-access: possible always (you cannot prevent anyone from reading your contract variables)
- Write-access: possible only if you've implemented in advance a function which allows it
Now let's examine each one of these access types...
Reading is always possible, but easier to implement if you've implemented in advance a function which allows it. Luckily for you, by declaring the contract variable public
, you've implicitly implemented such function (i.e., the compiler did it for you).
The declaration in the TF_Minting
contract:
mapping (address => uint) public mintedTF
Has created the following function in that contract:
function mintedTF(address) public view returns (uint)
So in order to read this variable in the TF_Reward
contract, what you need to do is:
interface ITF_Minting {
function mintedTF(address) public view returns (uint);
}
contract TF_Reward {
ITF_Minting private immutable tfMinting;
constructor(ITF_Minting _tfMinting) {
tfMinting = _tfMinting;
}
function someFunc(address _claimant) {
uint256 amount = tfMinting.mintedTF(_claimant);
...
}
...
}
Writing is possible only if you've implemented in advance a function which allows it. Since you haven't done that in the TF_Minting
contract, what you'll need to do in the TF_Reward
contract is to maintain another mapping which indicates how much has been claimed so far.
Something like this:
contract TF_Reward {
mapping (address => uint) public claimedTF
function someFunc(address _claimant, uint amount) {
uint minted_amount = tfMinting.mintedTF(_claimant);
uint claimed_amount = claimedTF[_claimant] + amount;
require(claimed_amount <= minted_amount, "requested amount too large");
claimedTF[_claimant] = claimed_amount;
// proceed to handle the input `amount` as desired...
}
...
}
1 Like
It Always @barakman to the rescue.
Thanks ser, the solution works for me! 
However, I was also wondering about this particular block:
Writing is possible only if you've implemented in advance a function which allows it.
How can we exactly write and change the values of a mapping in the contract? So basically how will that function look like?
Is it going to be something similar to the below function implemented in the TF_Minting
smart contract? :
contract TF_Minting {
mapping (address => uint) public mintedTF;
function updateMapping(address claimant, uint256 _claimedAmount) external returns(uint256) {
mintedTF[claimant] -= _claimedAmount;
}
}
1 Like
Yes, if you haven't deployed the TF_Minting
contract yet, then that what you would need to do.
Of course, you'd need to restrict access to this function, such that only a specific account or accounts are permitted to execute it (in your current implementation, it can be executed by anyone and everyone).
Also, it doesn't look like a function which needs to return anything (and if it does need to, then you've left out that part, which means that your code will not even compile).