Aave aaveLendingPool.withdraw() return value validation - ethereum

I am writing a pull payment function and, as with any external call it is good practice validate the result and check successful execution. I am using the following interface:
interface IAaveLendingPool {
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
function withdraw(
address asset,
uint256 amount,
address to
) external;
function getReservesList() external view returns (address[] memory);
}
aAveLendingPool= IAaveLendingPool(0x0543958349aAve_pooladdress)
The interface provided by Aave doesn't specify a return either. The withdraw function of the LendingPool.sol contract returns external override whenNotPaused returns (uint256).
The question: Can I use the returned uint to validate successful execution or aAveLendingPool.withdraw() returns a boolean? Will the following work as expected?
///#notice assigns dai to caller
require( aaveLendingPool.withdraw(
address(dai),
amount,
msg.sender), "Error, contract does not have enough DAI")
Please provide a solidity docs link to external function call return value, if any.

According to the Consensys Diligence Aave V2 audit:
ERC20 implementations are not always consistent. Some implementations of transfer and transferFrom could return ‘false’ on failure instead of reverting. It is safer to wrap such calls into require() statements to these failures.
Therefore, wrapping the transfer call in a require check is safe and sufficient.
require( aaveLendingPool.withdraw(
address(dai),
amount,
msg.sender), "Error, contract does not have enough DAI")

Related

How to retrieve data from a SmartContract that is not listed in their ABI

I'm trying to retrieve the total supply of an ERC1155 SmartContract. This code was made by my friend and has been deployed. He took the code from OpenZeppelin with Burnable and Pausable presets.
The function totalSupply that I am trying to retrieve exists in the code. But, when I see the ABI, the totalSupply does not included.
(Sorry for small screenshot. Please see this screenshot in the new tab)
MyErc1155Contract compiled
This is where to get the ABI
Full code is here: click_this_to_go_to_pastebin
Then I am trying to write smartcontract to retrieve the totalSupply;
pragma solidity ^0.8.0;
contract TotSup {
uint256 public hasilBal;
uint256 public hasil;
function balanceOf(address erc1155_address,
address user_address,
uint256 nft_id) public {
(bool successA, bytes memory resultA) =
erc1155_address.call(abi.encodeWithSignature(
"balanceOf(address,uint256)",
user_address,
nft_id
));
hasil = abi.decode(resultA, (uint256));
}
function bal(address erc1155_address, uint256 nft_id) public {
(bool successA, bytes memory resultA) =
erc1155_address.call(
abi.encodeWithSignature("totalSupply(uint256)", nft_id
));
hasilBal = abi.decode(resultA, (uint256));
}
}
I test my idea with writing another function balanceOf and it works perfectly.
And for the totalSupply in function bal is fail.
Is it possible to retrieve or calling function which is not included in the ABI? If yes, how to achieve that? And last, why call balanceOf still need for paying gas for just retrieving the data?
When a function exists in the code when you compile the code it reflects in the ABI, Without the function signature, you can't call the function.
As for your second answer, balanceOf in TotSup will cost you gas as it is not a view function.

solidity smart contract encode function for safety reason

I have one simple question.
So when we deal with smart contract on chain,
why don't we make encode function just in case for safety?
for example,
function encodeFunction(address _callee, bytes calldata _callData, uint256 _value) public returns (bool) {
(bool success, bytes memory returnData) = callee.call{vaule: _value}(_callData);
require(success, "tx failed");
return success;
}
Suppose that we are able to figure out any contract address and calldata, Isn't it much safer to have this kind of function to deal with any situation?
Wouldn't someone just listen to the encodeFunction and its parameters? For example etherscan allows users to see function calls and parameters .That would defeat the whole purpose of your encode function.
Also having this kind of function defeats the whole purpose of transparency of the concept blockchain.

Avoid using solidity's transfer()/send()?

I came across this article dated 2019/9 about avoiding using solidity's transfer()/send(). Here is the reasoning from the article:
It looks like EIP 1884 is headed our way in the Istanbul hard fork. This change increases the gas cost of the SLOAD operation and therefore breaks some existing smart contracts.
Those contracts will break because their fallback functions used to consume less than 2300 gas, and they’ll now consume more. Why is 2300 gas significant? It’s the amount of gas a contract’s fallback function receives if it’s called via Solidity’s transfer() or send() methods. 1
Since its introduction, transfer() has typically been recommended by the security community because it helps guard against reentrancy attacks. This guidance made sense under the assumption that gas costs wouldn’t change, but that assumption turned out to be incorrect. We now recommend that transfer() and send() be avoided.
In remix, there is a warning message about the code below:
(bool success, ) = recipient.call{value:_amount, gas: _gas}("");
Warning:
Low level calls: Use of "call": should be avoided whenever possible. It can lead to unexpected behavior if return value is not handled properly. Please use Direct Calls via specifying the called contract's interface. more
I am not an expert on gas cost over execution of smart contract and security. So I post this article and would appreciate thoughts and comments about it.
First, it's good to know about the fallback function in Solidity:
It has no name, no arguments, no return value, and it can be defined as one per contract, but the most important feature is it is called when a non-existent function is called on the contract such as to send or transfer or call.value()(""). So if you want to send Ether directly to an address which is a contract address, the fallback function of the destination contract will be called.
If the contract's fallback function not marked payable, it will throw an exception if the contract receives plain ether without data.
Now let's look at the reentrancy attack
contract VulnerableContract {
mapping(address => uint) public balances;
function deposit() public payable {
require(msg.value > 1);
balances[msg.sender] += msg.value;
}
function withdraw(uint _amount) public {
require(balances[msg.sender] >= _amount, "Not enough balance!");
msg.sender.call.value(_amount)("");
balances[msg.sender] -= _amount;
}
function getBalance() view public returns(uint) {
return address(this).balance;
}
fallback() payable external {}
}
VuinerableContract has a withdraw function which sends Ether to the calling address. Now the calling address could be a malicious contract such as this :
contract MaliciousContract {
VulnerableContract vulnerableContract = VulnerableContract(0x08970FEd061E7747CD9a38d680A601510CB659FB);
function deposit() public payable {
vulnerableContract.deposit.value(msg.value)();
}
function withdraw() public {
vulnerableContract.withdraw(1 ether);
}
function getBalance() view public returns(uint) {
return address(this).balance;
}
fallback () payable external {
if(address(vulnerableContract).balance > 1 ether) {
vulnerableContract.withdraw(1 ether);
}
}
}
When the malicious contract call the withdraw function, before reducing the balance of the malicious contract, it's fallback function will be called at it can steal more Ether from the vulnerable contract.
So by limiting the gas amount used by the fallback function up to 2300 gas we could prevent this attack. It means we can not put complex and expensive commands in the fallback function anymore.
Look at this for more information: https://swcregistry.io/docs/SWC-107
From Consensys article, they are saying use .call() instead of .transfer() and .send(). Only argument is that all three now sends more gas than 2300. Thus making it possible for reentrancy.
This comes to another conclusion that, regardless of all above, it is important to use checks-effects-interactions pattern to prevent reentracy attack.

How ERC20 tokens control access to their functions?

Here is my question (basically, I want to know if I am right or mistaken):
First of all, we have standard ERC20:
contract ERC20Interface
{
function transfer(address _to, uint _value) public returns (bool success);
function transferFrom(address _from, address _to, uint _value) public returns (bool success);
function approve(address _spender, uint _value) public returns (bool success);
.....
}
Then, in a CrowdSale, we have a token, derived from it:
contract ICO is Ownable {
...
MyToken public m_token;
...
function ICO() public {
m_token = new MyToken();
...
Then the crowdsale ends. The token with list of all people (addresses) that bought it becomes "free" of crowd sale contract:
function finish() onlyOwner public {
if(goalReached()) {
m_token.transferOwnership(m_addrOwner);
My questions:
1. For this token to be traded on exchanges, I have to somehow provide these exchanges with token's address. Where should I get it?
2. Am I correct? Is it how it supposed to work?
In other words, if a token is a separate contract, passed to ICO contract by address, I can see how exchanges can trade it after the end of crowd sale: they have that same address.
But I see a lot of crowdsales on Etherscan, that create contract internally (like in code snippets above). How do I make it "tradable" after the end of a crowd sale in this case?
Thanks.
Most exchanges will only support your token if they see value in it. You'd have to contact the exchanges and they will evaluate if it's worth it to them based on the demand for your token. Even then, they will most likely ask for payment up front before listing.
For example, Bittrex has their submission process documented here. They offer free listing once you pass their verification process (along with some non-free services). Other exchanges follow a similar process.
The contract address you're looking for that you'd have to provide is returned to your client when you deploy your token contract. If you somehow lose the address in your client, you can find it on etherscan.io by searching for the token name/symbol (assuming your token contract follows the ERC20 spec) or by transaction hash. You can also retrieve the address in code:
function getTokenAddress() constant returns (address) {
return address(m_token);
}
Outside of an exchange, you can also do private transfers of tokens by simply adding the token contract address to a wallet like Mist or Parity and sending tokens between addresses.
Note that all of this is independent of the crowd sale. The crowd sale is a separate contract that is used to raise money and do the initial token distribution.

Creating instance of contract inside another contract and calling it's methods results in thrown exception

I have 2 basic contracts: one is for token and the second is for sale.
Token сontract:
contract MyToken is StandardToken, Ownable {
string public constant name = "My Sample Token";
string public constant symbol = "MST";
uint32 public constant decimals = 18;
function MyToken(uint _totalSupply) {
require (_totalSupply > 0);
totalSupply = _totalSupply;
balances[msg.sender] = totalSupply;
}
}
Sale Contract
contract Sale {
address owner;
address public founderAddress;
uint256 public constant foundersAmount = 50;
MyToken public token = new MyToken(1000);
uint256 public issuedTokensAmount = 0;
function Sale() {
owner = msg.sender;
founderAddress = 0x14723a09acff6d2a60dcdf7aa4aff308fddc160c;
token.transfer(founderAddress, foundersAmount);
}
function() external payable {
token.transfer(msg.sender, 1);
owner.transfer(msg.value);
}
}
StandardToken and Ownable are all standard implementations from OpenZeppelin repository. Full contract source is available here.
So basically in my Sale Contract I create an instance of my token contract with fixed supply and assign all of the tokens to the caller. Then I transfer some amount of tokens to founder address. When I try to send some ethereum to Sale contract I'm attempting to transfer some of my tokens to the sender (Running all code in Remix browser, I create an instance of Sale contract and call "fallback" method specifying some ether amount). However, this fails with "Exception during execution. (invalid opcode). Please debug the transaction for more information." message. All that I can see when debugging is that code fails in payable method at line:
token.transfer(msg.sender, 1);
I can't see the exact reason for this as I'm not able to step into this method and see whats going on inside.
Interesting thing is that when I remove a call to transfer method on token instance in Sale Contract constructor - code seems to run fine without any exceptions.
What am I missing?
I debugged into the the contract using remix, and the invalid opcode is thrown by:
290 DUP8
291 DUP1
292 EXTCODESIZE
293 ISZERO
294 ISZERO
295 PUSH2 012f
298 JUMPI
299 PUSH1 00
301 DUP1
302 INVALID
I left out the rest, but essentially it loads the address of the token contract and calls EXTCODESIZE which retrieves the contracts code size, and checks that it's not equal to 0 (the token contract exists), unfortunately, it did equate to 0. At this point, I'm unsure whether this is a limitation in remix or I've misunderstood the setup.
I tried the identical contract setup on truffle + testrpc and it deployed, accepted the currency successfully. Do note however that testrpc indicated:
Gas usage: 59137
Meaning that this is above the default sendTransaction w/ no data default (21,000 gas). This means that in a live environment, ensure that you inform users to include extra gas, otherwise the fallback function would probably fail due to OOG errors.
The reason behind this is that you're using a fallback function. Try using a normal function and it should happen.