- The user may allow contract@active to satisfy their @active permission
cleos set account permission MYACCOUNT active '{"threshold": 1, "keys":[{"key":"MY_PUBLIC_ACTIVE_KEY", "weight":1}], "accounts":[{"permission":{"actor":"CONTRACT_NAME","permission":"eosio.code"},"weight":1}], "waits":[] }' owner -p MYACCOUNT
- The user may set up a sub-permission (for example @xfer), link that as the minimum permission to eosio.token::transfer and allow contract@active to satisfy that permission
cleos set account permission MYACCOUNT xfer '{"threshold": 1, "keys":[], "accounts":[{"permission":{"actor":"CONTRACT_NAME","permission":"eosio.code"},"weight":1}], "waits":[] }' active -p MYACCOUNT
cleos set action permission MYACCOUNT eosio.token transfer xfer -p MYACCOUNT
- require that the transfer be explicit (not inline) and then use the notification that is sent to your contract to (temporarily) record the details and read/assert/process them in a second action directly to your contract.
So this one is slightly more complicated. First of all, you would set up a permission for the contract to withdraw funds from your account as shown in option 2. Then you would have to load a smart contract to your account, and that contract would have a notify action linked to the transfer function. In this notify action, you would basically write some checks that would tell you that the amount taken was as it was expected to be, and do whatever other checks are necessary as well. This still isn't foolproof, because even if you limit the amount of money that can be withdrawn to something small like 1 EOS, there is nothing stopping the contract from calling that action many times to drain your account and/or use up your CPU and NET bandwidth.
An example of how the smart contract might look:
// Set up the transfer function to be called if a transfer occurs
void transfer( eosio::name from, eosio::name to, eosio::asset quantity, std::string memo )
{
if(from == get_self()) return;
if(to == get_self() && from == CONTRACT)
{
eosio::check(quantity.amount == 10000, "I expect that CONTRACT only ever takes 1 EOS at a time from my account");
// Add as many more checks here as are necessary
}
}