How to transfer funds from smart contract to account OTHER than msg.sender? - solidity

I am trying to transfer part of funds stored in a smart contract to an account other than the one calling the function (msg.sender). My function is pretty much like this:
function getFunds(address addr, uint amount) public {
require (address.this(balance)>= amount);
addr.transfer(amount);
}
What I get when I compile in Truffle is:
Member "transfer" not found or not visible after argument-dependent lookup in address.
As if it is looking for members in a struct.
Thanks for any help.

Since solidity 0.5 addresses should be payable in order to transfer eth to them
function getFunds(address payable addr, uint amount) public {
require (address.this(balance)>= amount);
addr.transfer(amount);
}
For mapping of a struct you can use like this
contract testContract {
mapping(uint256 => test) testAddressMapping;
struct test {
address payable testAddress;
}
function testFunction() external{
testAddressMapping[0].testAddress.transfer(100);
}
}

Related

What is missing from this Smart Contract?

I am working on a smart contract, and my goal is that when a certain (variable) amount of eth gets send to the contract, it gets split and payed to three adresses. I currently have this code. Am I missing something? It doesn't work in Remix unfortunately. Thanks in advance for your valuable time!
`pragma solidity ^0.6.0;
contract PaymentSplitter {
address payable addressOne;
address payable addressTwo;
address payable addressThree;
uint256 amount;
constructor(address payable _addressOne = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2, address payable _addressTwo = 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db, address payable _addressThree = 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB) public {
addressOne = _addressOne;
addressTwo = _addressTwo;
addressThree = _addressThree;
}
function splitPayment(uint256 _amount) public {
amount = _amount;
addressOne.transfer(_amount / 3);
addressTwo.transfer(_amount / 3);
addressThree.transfer(_amount / 3);
}
function getSplitAmount() public view returns (uint256) {
return amount;
}
// This will be invoked when the contract receives a payment
function() external payable {
splitPayment(msg.value);
}
}`
We tried various smart contract, but without any significant results
I modified your smart contract. I put some notes, to understand you some errors in your logic:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract PaymentSplitter {
address payable addressOne;
address payable addressTwo;
address payable addressThree;
uint256 amount;
constructor(address _addressOne, address _addressTwo, address _addressThree) public {
addressOne = payable(_addressOne);
addressTwo = payable(_addressTwo);
addressThree = payable(_addressThree);
}
// NOTE: Avoid passing parameter with value because with this statement 'address(this).balance' I receive the entire amount of Ether stored in smart contract
function splitPayment() public {
// NOTE: I retrieve entire amount stored in smart contract balance after send value to it
uint smartContractBalance = address(this).balance;
// NOTE: Since smart contract balance should be divided into three equal part the amount, I make this operation one time and put the value inside 'amount' variable. Then
// I transfer the equal amount to three accounts.
amount = smartContractBalance / 3;
addressOne.transfer(amount);
addressTwo.transfer(amount);
addressThree.transfer(amount);
}
function getSplitAmount() public view returns (uint256) {
return amount;
}
// This will be invoked when the contract receives a payment
receive() external payable {
splitPayment();
}
}
NOTE: Consider to use address.call{value}() for send amount from smart contract to accounts.
Is this a better contract? A few changes, and different amounts have to be sent to different addresses.
pragma solidity ^0.8.17;
contract Blockbook{
address payable public address1;
address payable public address2;
address payable public address3;
constructor(address payable _address1, address payable _address2, address payable _address3) public {
address1 = _address1;
address2 = _address2;
address3 = _address3;
}
function splitPayment(uint amount) public payable {
address1.transfer(amount * 0.8);
address2.transfer(amount * 0.1);
address3.transfer(amount * 0.1);
}
receive() external payable {
splitPayment(msg.value);
}
function updateAddresses(address payable _address1, address payable _address2, address payable _address3) public {
address1 = _address1;
address2 = _address2;
address3 = _address3;
}
}

payments ( pre set value) in solidity

i am developing a Movie renting smartcontract. Where the owner can add new movies, clients can search movies and pay for the movies they select.Adding and searching is working to my liking.
problem: i want to develop the pay function as such- where it takes one argument( the title of the movie) and clients has to pay the exact amount set by the owner, he can not pay less then the price.
for example: owner add a movie: title-titanic,price-10 eth. when client use the pay function he put the title titanic and pay 10 eth. if he tries to pay less or more the transaction will not be successful.
here is the code
pragma solidity 0.8.7;
// SPDX-License-Identifier: MIT
contract Movie{
address public owner;
struct Move{
uint year;
uint price;
}
mapping (string => Move ) public movieInfo;
mapping(uint => Move) amount;
constructor() payable{
owner= msg.sender;
}
function addMovie(string memory _title, uint _year, uint _price) public {
require( msg.sender==owner);
movieInfo[_title]= Move(_year, _price);
}
function pay(string memory _title) public payable{
}
function totalFunds() public view returns(uint){
return address(this).balance;
}
}
Don't think that this kind of stuff is good to store into the blockchain ATM, due to the highly cost of storing.
In case you would like to have it:
mapping(string -> address[]) paidUsers;
function pay(string memory _title) public payable {
require(msg.value == movieInfo[_title].price, "Invalid price for the film");
paidUsers[_title].push(msg.sender);
}

Transaction Reverted even though I have a payable fallback function to receive eth, when I deploy without sending eth it works

Here is my code:
pragma solidity 0.8.6;
import "./Allowance.sol";
contract SharedWallet is Allowance {
event MoneySent(address indexed _beneficiary, uint _amount);
event MoneyReceived(address indexed _from, uint _amount);
function withdrawMoney(address payable _to, uint _amount) public ownerOrAllowed(_amount) {
require(_amount <= address(this).balance, "Contract doesn't own enough money");
if(!isOwner()) {
reduceAllowance(msg.sender, _amount);
}
emit MoneySent(_to, _amount);
_to.transfer(_amount);
}
function renounceOwnership() public override onlyOwner {
revert("can't renounceOwnership here"); //not possible with this smart contract
}
fallback () external payable {
emit MoneyReceived(msg.sender, msg.value);
}
}
Are you trying to send Ether to the contract as you deploy it? As I do not think you can do that easily. Well, there is a hacky way. Ethereum contract address is deterministic, i.e. knowing the creator's address and their nonce you can calculate the future address of your smart contract. And then send ETH to that address prior to deploying the contract.

A Lottery Solidity Smart Contract Accept token as payment instead of ether

pragma solidity ^0.4.21;
contract Lottery {
address public manager;
address[] public players;
constructor() public {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint) {
return uint(keccak256(abi.encodePacked(block.difficulty, now, players)));
}
function pickWinner() public restricted {
uint index = random() % players.length;
players[index].transfer(address(this).balance);
players = new address[](0);
}
function getPlayers() public view returns (address[]) {
return players;
}
modifier restricted() {
require(msg.sender == manager);
_;
}
}
I want o change the function
function enter() public payable {
require(msg.value > .01 ether);
players.push(msg.sender);
}
Instead of ether, user use our token/erc20 to enter the lottery
You can define an interface (in your contract) of the token contract. Since you're only going to be using the transferFrom() function, this is the only function that you need to define in the interface (no matter that the token contract contains other functions as well).
interface IERC20 {
function transferFrom(address _from, address _to, uint256 _amount) external returns (bool);
}
The you can execute the transferFrom() function of the token, passing it arguments:
from: the user executing your enter() function
to: your contract
amount: Assuming the token has 18 decimals (most tokens do), you can use the ether helper unit, because it effectively calculates "0.01 * 10^18 (or 10^16, or 10000000000000000) of the token smallest units", which is 0.01 of the token. Otherwise, you'll need to recalculate this number based on the token decimals.
function enter() public payable {
IERC20 token = IERC20(address(0x123)); // Insert the token contract address instead of `0x123`
require(token.transferFrom(msg.sender, address(this), .01 ether));
players.push(msg.sender);
}
Important: Mind that the user needs to approve() your contract to spend their tokens beforehand (from their address), otherwise the token transfer would fail. There's a security reason for that, read more about it in the bottom part of this answer.

How to make an API call in solidity?

I have a smart contract that I’m trying to make, it pays out the winners of my League of Legends tournament. However I’m running into an issue. I need to make an API call to get the winner of the match, I have a simple URL that I’ve make.
"example-winner.com/winner"
And it returns simple JSON with the address of the winner:
{"winner":"0xa7D0......."}
However, I’m not sure how to make the API call to the outside function. I know I need to use some sort of oracle technology.
Any thoughts? Below is my code:
pragma solidity ^0.4.24;
contract LeagueWinners{
address public manager;
address[] public players;
uint256 MINIMUM = 1000000000000000;
constructor() public{
manager = msg.sender;
}
function enter() public payable{
assert(msg.value > MINIMUM);
players.push(msg.sender);
}
function getWinner() public{
assert(msg.sender == manager);
// TODO
// Get the winner from the API call
result = 0; // the result of the API call
players[result].transfer(address(this).balance);
// returns an adress object
// all units of transfer are in wei
players = new address[](0);
// this empties the dynamic array
}
}
You can use Chainlink as your Oracle.
As many have mentioned, you will need an oracle to get your API call. Something that is important to note, your contract is actually asking an oracle to make your API call for you, and not making the API call itself. This is because the blockchain is deterministic. For more information see this thread.
To answer your question, you can use the decentralized oracle service Chainlink.
You'd add a function:
function getWinner()
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(JOB, address(this), this.fulfill.selector);
req.add("get", "example-winner.com/winner");
req.add("path", "winner");
sendChainlinkRequestTo(ORACLE, req, ORACLE_PAYMENT);
}
For the purpose of the following exmaple, we are going to pretend you want to return a uint256 instead of an address. You can return a bytes32 and then convert it to an address, but for simplicity let's say the API returns the index of the winner. You'll have to find a node and jobId that can make a http.get request and return a uint256 object. You can find nodes and jobs from market.link. Each testnet (Ropsten, Mainnet, Kovan, etc) has different node addresses, so make sure you pick the right ones.
For this demo, we are going to use LinkPool's ropsten node
address ORACLE=0x83F00b902cbf06E316C95F51cbEeD9D2572a349a;
bytes32 JOB= "c179a8180e034cf5a341488406c32827";
Ideally, you'd choose a number of nodes to run your job, to make it trustless and decentralized. You can read here for more information on precoordinators and aggregating data. disclosure I am the author of that blog
Your full contract would look like:
pragma solidity ^0.6.0;
import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";
contract GetData is ChainlinkClient {
uint256 indexOfWinner;
address public manager;
address payable[] public players;
uint256 MINIMUM = 1000000000000000;
// The address of an oracle
address ORACLE=0x83F00b902cbf06E316C95F51cbEeD9D2572a349a;
//bytes32 JOB= "93fedd3377a54d8dac6b4ceadd78ac34";
bytes32 JOB= "c179a8180e034cf5a341488406c32827";
uint256 ORACLE_PAYMENT = 1 * LINK;
constructor() public {
setPublicChainlinkToken();
manager = msg.sender;
}
function getWinnerAddress()
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(JOB, address(this), this.fulfill.selector);
req.add("get", "example-winner.com/winner");
req.add("path", "winner");
sendChainlinkRequestTo(ORACLE, req, ORACLE_PAYMENT);
}
// When the URL finishes, the response is routed to this function
function fulfill(bytes32 _requestId, uint256 _index)
public
recordChainlinkFulfillment(_requestId)
{
indexOfWinner = _index;
assert(msg.sender == manager);
players[indexOfWinner].transfer(address(this).balance);
players = new address payable[](0);
}
function enter() public payable{
assert(msg.value > MINIMUM);
players.push(msg.sender);
}
modifier onlyOwner() {
require(msg.sender == manager);
_;
}
// Allows the owner to withdraw their LINK on this contract
function withdrawLink() external onlyOwner() {
LinkTokenInterface _link = LinkTokenInterface(chainlinkTokenAddress());
require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer");
}
}
This would do about everything you need.
If you can't adjust the API to return a uint, you can return a bytes32 and then convert it to an address or a string.
function bytes32ToStr(bytes32 _bytes32) public pure returns (string memory) {
bytes memory bytesArray = new bytes(32);
for (uint256 i; i < 32; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
You cannot. The vm does not have any I/O outside of the blockchain itself. Instead you will need to tell your smart contract who the winner is and then the smart contract can just read the value of that variable.
This design pattern is also known as the "oracle". Google "Ethereum oracle" for more info.
Basically your web server can call your smart contract. Your smart contract cannot call your web server. If you need your smart contract to access a 3rd party service then your web server will need to make the request then forward the result to solidity by calling a function in your smart contract.
You didn't properly explain what you are trying to do. Are you having trouble with the solidity code? or rather with your server? Here is an edited version. See if it helps.
pragma solidity ^0.4.24;
contract LeagueWinners{
address public manager;
//address[] public players;
uint256 MINIMUM = 1000000000000000;
constructor() public{
manager = msg.sender;
}
struct Player {
address playerAddress;
uint score;
}
Player[] public players;
// i prefer passing arguments this way
function enter(uint value) public payable{
assert(msg.value > MINIMUM);
players.push(Player(msg.sender, value));
}
//call this to get the address of winner
function winningPlayer() public view
returns (address winner)
{
uint winningScore = 0;
for (uint p = 0; p < players.length; p++) {
if (players[p].score > winningScore) {
winningScore = players[p].score;
winner = players[p].playerAddress;
}
}
}
// call this to transfer fund
function getWinner() public{
require(msg.sender == manager, "Only a manager is allowed to perform this operation");
// TODO
address winner = winningPlayer();
// Get the winner from the API call
//uint result = 0; // the result of the API call
winner.transfer(address(this).balance);
// returns an adress object
// all units of transfer are in wei
delete players;
// this empties the dynamic array
}
}
At least that is what I understand by your question.