Reputation: 7593
I came from Java OOP background and understand interfaces.
Currently working on a simple budgeting app (https://github.com/compound-developers/compound-supply-examples) that takes ETH or Stablecoin and put in in Compound and earn interest.
My confusion is how Solidity Interfaces are used. I came from OOP (Java) background and very familiar with interfaces.
So in this code(MyContracts.sol
) you can see that there is a mint()
function in the interface. However, there is no implementation for it but you can see that it's used here uint mintResult = cToken.mint(_numTokensToSupply);
without any implementation.
Can anyone shade some lights on how interface functions are used without implementations ? When you call mint in this case, which code is actually being executed ?
Upvotes: 6
Views: 3514
Reputation: 49263
interface
is used for type casting. from this contract
interface IReceiver {
function receiveTokens(address tokenAddress, uint256 amount) external;
}
inside contract
contract UnstoppableLender is ReentrancyGuard {
.....
function flashLoan(uint256 borrowAmount) external nonReentrant {
require(borrowAmount > 0, "Must borrow at least one token");
uint256 balanceBefore = damnValuableToken.balanceOf(address(this));
require(balanceBefore >= borrowAmount, "Not enough tokens in pool");
assert(poolBalance == balanceBefore);
damnValuableToken.transfer(msg.sender, borrowAmount);
// that means msg.sender has receiveTokens functionality
// we are making sure that who ever is calling this function, has this method implemented
// we can conclude that ms.sender is a contract address
IReceiver(msg.sender).receiveTokens(
address(damnValuableToken),
borrowAmount
);
.......
}
msg.sender
is the address that calling flashLoan
function. By casting with the IReceiver
interface we are saying that whichever contract address is calling flashLoan
function must have it is own receiveTokens
function implemented.
If you look at the contract that calling the flashLoan
function, in fact has receiveTokens
function receiveTokens(address tokenAddress, uint256 amount) external {
require(msg.sender == address(pool), "Sender must be pool");
// Return all tokens to the pool
require(IERC20(tokenAddress).transfer(msg.sender, amount), "Transfer of tokens failed");
}
Upvotes: 0
Reputation: 7593
I believe I got the main issue that was confusing to me.
So if you come from OOP background this what we know about interfaces:
interface IERC20 {
function totalSupply() external view returns (uint256);
}
contract XYZ is IERC20 {
// then implement totalSupply here
function totalSupply() external view returns (uint256) {
// implementiation goes here.
address public add='0x123...4'
}
So at this point you can call XYZ's totalSupply()
and you should be fine.
However, there is another way of using interfaces in Solidity. I will take this code from compound protocol as an example (https://github.com/compound-developers/compound-supply-examples)
If you see MyContracts.sol
, it has the following interface:
interface CEth {
function mint() external payable;
function exchangeRateCurrent() external returns (uint256);
function supplyRatePerBlock() external returns (uint256);
function redeem(uint) external returns (uint);
function redeemUnderlying(uint) external returns (uint);
}
However, there is no place in our contract that uses the keyword IS and implements any of the methods. So you might ask how is our interface being used ?
Now let's go back to MyContract
contract in MyContracts.sol
file and see this code under supplyEthToCompound
function:
CEth cToken = CEth(_cEtherContract);
Here we are providing CEth interface with a contract address of Compound (i.e _cEtherContract
and the contract at that address has a mint() function.)
When you call cToken.exchangeRateCurrent();
on the next line, what happens is we are basically calling a function exchangeRateCurrent on Compound Contract.
At first it seems like exchangeRateCurrent has no implementation in the file we are calling it but the implementation resides at _cEtherContract address.
I hope this clears the confusion especially if you come from traditional OOP background.
Feel free to point out anything that is misleading in my answer.
Upvotes: 20