Depending on your codebase, you may need to call the token contract directly from the staking contract. You'll need either the source code of the token contract you wish to call, or an interface of it, or at the very least an interface that defines the functions you need to interact with (though the latter is likely not advisable). (Here's the link to Vyper's Interfaces, if you prefer Vyper to Solidity.)
To break down exactly how using the interface to interact with the contract works, let's say the token's interface contract is called Foo
, and the file for the Foo contract is in the same directory as your staking pool at compile time:
pragma solidity ^0.8.2;
import "./Foo.sol";
contract StakingPool {
Foo private fooContract
constructor(address fooAddress) {
fooContract = Foo(fooAddress);
}
function approveStakingPoolOnFoo(uint256 amount) public returns(bool) {
require(fooContract.approve(msg.sender, address(this), amount),
"approveOnFoo:approval failed");
return true;
}
}
To break it down, the contract is imported, then the contract name ("Foo
") can be used as a data type to create a variable that this contract will treat as a representation of the contract you wish to interact with. In the example, we tell the staking contract in the constructor what the address of the token contract is, and tell it to treat the code at that address like a Foo
. (That's the fooContract = Foo(fooAddress);
line.) Then we can use that to call functions on the Foo contract - the example given is for Approve, though it is equally applicable to balanceOf
and any other public
or external
function.
Note that oftentimes calls to another contract don't need to be done through the actual contract, but can be done instead through the web interface using a web3 library. A lot depends on your specific case.
Hope that's helpful!