I am trying to understand exactly how to programatically create an address within a smart contract and then send eth/wei from that address to another address if I've created multiple such addressses.
For example
Contract MultiAddress {
Struct User {
string name;
string payable address account;
}
mapping(uint256 => User) users;
constructor() {}
function createUser(string memory name) {
...
}
function transferFromUser(uint256 id, address payable recipient, uint256 amount) {
// I want to send an amount from the person at id within the struct mapping to the recipient
users[id].account.send({to: recipient, amount: amount})
}
}
Is this possible to do? Can I only have one payable address per contract? I want to set up a modified version of access control to allow the user to be allowed to transfer funders from the user account (without having to deploy multiple smart contracts).
Any clarification is much appreciated!
Thanks,
You cannot create an EOA account in a smart contract, but you can create a smart contract in a smart contract.
2 Likes
In such case, amount from payable address has to be get transferred to contract, and from contract you can send the funds the funds to recipient.
function transferFromUser(uint256 id, address payable recipient, uint256 amount) public payable {
// Receive payment from user
// Msg.value will get collected from user
// Funds will be under control of contract
// Now from contract funds can be transferred to recipient
// *** Make sure you put necessary check while receiving msg.value***
// require(users[id].account == msg.sender) By this you ensure payable address is caller
// require(msg.value == amount) By this you ensure user is passing required amount
recipient.transfer(msg.value);
}
Thanks @maxareo! This is the approach I took. I created a simple Treasury contract and created an instance of this contract inside a struct User in my main contract. Then referenced that user by id (similar to the ERC1155 approach).
So the result was something like this for those of you attempting a similar use case:
// Set up the simple Treasury contract
contract Treasury {
// The token id for the Gatherize Token
uint256 tid;
// The address of the owner of the token
address owner;
constructor(
uint256 tokenId,
address ownerAddress
) {
// Initialize contract and connect to token
tid = tokenId;
owner = ownerAddress;
}
// These functions are necessary for contracts that accept ETH and WEI!
receive() external payable {}
// This one is called when no function matches the request ex send, transfer, call
fallback() external payable {}
function _moveFunds(address payable to, uint256 amount, string memory description) public virtual {
// Move funds from this contract to any payable address
// And set whatever conditions you want to control the funds
}
}
// Imports the Treasury solidity file from wherever it may be
Treasury treasury;
contract MultiAddress {
Struct User {
uint256 id;
string name;
string payable address account;
Treasury treasury;
}
mapping(uint256 => User) users;
constructor() {}
function createUser(string memory name) {
...
}
function transferToTreasury(uint256 id, uint256 amount) {
// Send funds to the treasury for that specific user
payable(users[id].treasury).transfer(amount);
}
}
I was getting confused because you are able to set address variables within contracts, which gave me the sense that these addresses could also be payable in which case you could send ETH to them. But these can only reference payable addresses outside the contract. The contract itself can also be payable but has one payable address per instance.
Thanks!
Not sure if I understand this sentence.
So in a situation like this:
address payable someExternalAddress
constructor(address payable addr) {
someExternalAddress = addr;
}
You would be passing an account into the contract through the constructor.
However, when you use:
// These functions are necessary for contracts that accept ETH and WEI!
receive() external payable {}
// This one is called when no function matches the request ex send, transfer, call
fallback() external payable {}
You are using the payable address of the contract itself. At least this is my current understanding, feel free to let me know if I'm missing something.
Thanks!