Is my Solidity code correct and safe to use - ethereum

I am very new using Solidity to create Ethereum contracts and would like to know if the contract I have created is first correct and safe to use.
What I am doing in this contract is allowing the user to send some ETH from their wallet to a friends wallet but also take a $0.05 fee (194740000000000 wei at time of writing) for using my services.
Now when testing the contract using remix all works fine, but as I am new to solidity contracts I just wanted to get some expert opinions to make sure I am doing everything correctly and safety.
My contract code is:
pragma solidity ^0.5.1;
contract Forwarder {
address payable public receiversAddress = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C;
address payable public feeAddress = 0xdD870fA1b7C4700F2BD7f44238821C26f7392148;
constructor() payable public {
uint amountToSendReceiver = msg.value-194740000000000;
receiversAddress.transfer(amountToSendReceiver);
feeAddress.transfer(194740000000000);
}
}
As mentioned everything works fine in remix, but is my contract code correct and safe to use? There is no way to use the contract after to maybe steal funds or have any vulnerabilities?

Yes, your code is pretty safe. The only thing I would like to add is line with require condition for code maintainability
And if your vars are not changeable, its better to use constant to make your contract cheaper for deploy ;)
Functions can be declared constant in which case they promise not to
modify the state.
pragma solidity ^0.5.1;
contract Forwarder {
address payable public constant receiversAddress = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C;
address payable public constant feeAddress = 0xdD870fA1b7C4700F2BD7f44238821C26f7392148;
uint256 constant feeAmount = 194740000000000;
constructor() payable public {
require(msg.value >= feeAmount); // for maintainability, your tx will be reverted anyway, just to show why
feeAddress.transfer(feeAmount); // transfer fee
receiversAddress.transfer(address(this).balance); // transfer remaining amount of msg.value
}
}

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.

How can I do a proxy call on anchor protocol terra ethereum transfer. error: UNPREDICTABLE_GAS_LIMIT

I want to make a smart contract that deposits UST on the eth anchor protocol, by using the deposit function. Here you can find the docs of this function I try to call. https://docs.anchorprotocol.com/ethanchor/ethanchor-contracts/router . The function gets called trough a proxy contract. I found the implementation address by reading the proxy contract on etherscan.
TestContracts on Ropsten testnet:
proxy: 0x7537aC093cE1315BCE08bBF0bf6f9b86B7475008
etherscan: https://ropsten.etherscan.io/address/0x7537aC093cE1315BCE08bBF0bf6f9b86B7475008
implementation (ROUTERV2): 0x2ba0010394eb3e41454c7d79c0fb6e0deb67284b
etherscan: https://ropsten.etherscan.io/address/0x2ba0010394eb3e41454c7d79c0fb6e0deb67284b
I imported the ROUTERV2 contract for calling the proxy with the abi of the implementation.
my execution order is:
deploying the contract
approving the contract for spending the tokens from the sender using ethers.
approveUST function on smart contract (I am not sure if this is necessary)
calling the depositStable function.
I get the following error when calling the depositStale function UNPREDICTABLE_GAS_LIMIT;
Below You see the contract I try to make. It should take the UST of the user and deposit it on eth anchor.
Here is a github link to the hardhat repo of the contract so you can simulate the bug and hopefully help me solving this issue.
https://github.com/tijgersoftware/Terra-anchor
I thank you for taking the time to read my question!
contract Anchor {
address public proxy;
address public operator;
address public USTAddress;
constructor(
address proxy_,
address operator_,
address USTAddress_
) public {
proxy = proxy_;
operator = operator_;
USTAddress = USTAddress_;
}
function approveUST() public {
ERC20(USTAddress).approve(
address(this),
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
);
}
function initDepositStable(uint256 amount) public {
RouterV2(proxy).initDepositStable(amount);
}
function depositUST(uint256 amount) public {
// InterfaceOfImplementationContract(proxyAddress).MethodBeingCalled(
// parameter,
// parameter,
// parameter
// );
ERC20(USTAddress).approve(
address(this),
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
);
RouterV2(proxy).depositStable(operator, amount);
}
}
tags: solidity, smart contracts, ethereum, anchor protocol, terra, brdige trasfer.

How to transfer an ERC721 token

I'm trying to transfer an ERC721 token, but I'm getting the error ERC721: transfer caller is not owner nor approved for the transferToken method.
Main.sol
import "./ERC721.sol";
import "./Counters.sol";
contract Main is ERC721 {
using Counters for Counters.Counter;
Counters.Counter internal _tokenIds;
address payable internal admin;
constructor() ERC721("MyToken", "TOKEN") {
admin = payable(msg.sender);
}
}
Auction.sol
import "./Main.sol";
contract Auction is Main {
struct AuctionInfo {
uint256 tokenId;
address highestBidder;
uint highestBid;
}
mapping(string => AuctionInfo) private _auctionInfo;
function createAuction(string memory id) public {
_tokenIds.increment();
uint256 newTokenId = _tokenIds.current();
_mint(msg.sender, newTokenId);
_auctionInfo[id].tokenId = newTokenId;
}
function transferToken(string memory id) public {
require(msg.sender == _auctionInfo[id].highestBidder, "You are not the highest bidder");
safeTransferFrom(address(this), _auctionInfo[id].highestBidder, _auctionInfo[id].tokenId);
}
// other methods...
}
The minting contract is this and the owner of the token is the msg.sender of the minting method if I'm not mistaken. Am I to use the approve (or setApprovalForAll) for this each time before transferring? I've tried this, payable(this), and address(this) for the safeTransferFrom method, but none seem to be working.
For example, I tried the following, but get the same revert message:
approve(address(this), _auctionInfo[id].tokenId);
this.safeTransferFrom(address(this), _auctionInfo[id].highestBidder, _auctionInfo[id].tokenId);
The main principle behind any Blockchain is that nobody on the blockchain network should be trusted, and still the transactions should happen fool proof, with no possibility of any cheating being done (barring of course of some hacking).
If you invoke the approve method from the Auction contract, then the msg.sender for the approve function in the ERC721 token contract is your auction contract address. So, in other words, your Auction Contract is trying to approve itself to sell someone else's NFTs, which is not very trustworthy.
What should really happen is that owner of the NFT should invoke the approve method of the ERC721 contract - i.e. the transaction that you send for the approve function call, should be signed by the NFT owner wallet address. This way, the msg.sender for the approve function in the ERC721 contract will be the owner of the NFT. As per the ERC721 standards, the owner of the NFT can approve anyone they want, to sell their NFT(s), as the no-trust in the network is still maintained (At least I should be able to trust myself). The approve method should be invoked from within your DAPP, before the transferToken function is invoked from the DAPP.
Hope that explains why you are unable to transfer your ERC721 tokens.
Because of the internal visibility of the ERC721._approve() function, you can effectively perform the approval for the user.
Then you'll be able to execute the safeTransferFrom(tokenOwner, receiver, tokenId) from your contract, because your contract address is approved to operate this specific token even though it belongs to the tokenOwner.
This snippet mints the token, assigning the ownership to the msg.sender. But then it also calls the _approve() function that doesn't contain any validations and simply assigns the approval of the token to the Auction address.
pragma solidity ^0.8;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
contract Auction is ERC721 {
constructor() ERC721("CollectionName", "Symbol") {}
function createAuction() public {
uint256 newTokenId = 1;
_mint(msg.sender, newTokenId);
_approve(address(this), newTokenId);
}
}
You can see from the screenshot that the owner is 0x5B... (the user address) and that the token is approved for 0xd9... (the contract address).
Note: The _approve() function is internal - it can be called from the ERC721 contract and contracts deriving from it (in your case Main and Auction), but it can't be called from external contracts or end user addresses.

Why can't I use this transferEther function to send Ether to the smart contract?

I have this code I have entered into Remix IDE, as ReceivedEther.sol, a standalone smart contract.
I've transferred 0.02 Ether to the smart contract, using MetaMask.
When I checked the smart contract's balance, it returns 200000000000000000, as expected.
If I try to use the transferEther function, however, and enter a number smaller than this - say, 0.005 ETH, or 50000000000000000 as the amount - it doesn't work using MetaMask.
When MetaMask prompts me it's never for that amount. It's for 0 ETH and 0.00322 gas fee (or whatever the gas is). Basically it always set the amount of ETH at 0 and only charges the fee.
Why can't I transfer an amount of ETH using this function in the Remix IDE with MetaMask?
pragma solidity ^0.8.0;
contract ReceivedEther {
function transferEther(address payable _recipient, uint _amount) external returns (bool) {
require(address(this).balance >= _amount, 'Not enough Ether in contract!');
_recipient.transfer(_amount);
return true;
}
/**
* #return contract balance
*/
function contractBalance() external view returns (uint) {
return address(this).balance;
}
}
Your code sends ETH (stated in the _amount variable) from the smart contract to the _recipient. So it doesn't require any ETH to be sent in order to execute the transferEther() function.
If you want your contract to accept ETH, the function that accepts it (or the general fallback() or receive() function) needs to be marked as payable.
Example:
pragma solidity ^0.8.0;
contract ReceivedEther {
receive() external payable {} // note the `payable` keyword
// rest of your implementation
}
Then you can send whathever amount of ETH to the smart contract address (without specifying any function to execute).
See more at https://docs.soliditylang.org/en/v0.8.5/contracts.html#receive-ether-function
If you want to prefill the amount in MetaMask from Remix IDE, you can use the "Value" input in the "Deploy & Run Transactions" tab.

Fetch pair price from Uniswap using smart contract function

I am relatively new to Solidity, I am trying to fetch the price of a pair with the following contract:
contract Uniswap {
constructor () public payable {
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
// calculate price based on pair reserves
function getTokenPrice(address pairAddress, uint amount) public payable returns(uint)
{
IUniswapV2Pair pair = IUniswapV2Pair(pairAddress);
IERC20 token1 = IERC20(pair.token1());
(uint Res0, uint Res1,) = pair.getReserves();
// decimals
uint res0 = Res0*(10**token1.decimals());
return((amount*res0)/Res1); // return amount of token0 needed to buy token1
}
}
but when I try to run on Remix the getTokenPriceit returns me the following error message:
The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.
Any idea why? I am trying to fetch the price of ETH/USDT so the using this website (https://v2.info.uniswap.org/pair/0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852) and with the pair address at the end of the URL. Thanks for the help!
When you deploy a contract in Remix, it deploys to a local network. (By default. You can change it and deploy to mainnet as well, if you inject a production Infura provider for example.)
The Uniswap pair contract 0x0d4a11... does not exist on the local network.
The easiest solution is to deploy your contract on the mainnet (where the 0x0d4a11... Uniswap pair contract exists).
Or you can find another Uniswap pair on a public testnet (well-known are Rinkeby, Ropsten, Goerli, and Kovan), and deploy your contract on the same testnet. Don't forget to change the testnet address of the uniswap pair that you pass to your getTokenPrice() function.
Or you can deploy the Uniswap pair contract and all of its dependencies and change the dependencies addreses (which is a lot of work - my guess is that it's dependend on the Uniswap router contract, the actual token contracts of the pair, maybe they are dependend on some other contract, ...) to your local network. From here it's the same - deploy your contract to the local network, and call the getTokenPrice() with the correct pair address.
You may also invoke uniswap's Subgraph using javascript