I am reading through the documentation of EOS Proxy contract but I am having hard time understanding the following

You can do this from a smart contract without using this intermediate proxy.

Inline transfer to proxy, then inline transfer from proxy. Proxy’s active would delegate to contract’s eosio.code The original contract would issue both transfers, but with a different auth.

Why does the original contract need to issue both the transfers? Do I then need a separate proxy contract or not?

up vote 1 down vote accepted

The text is misleading. There are still 2 contracts involved despite what is being said. To be sure

Proxy’s active would delegate to contract’s eosio.code

cannot be true unless there are 2 contracts in play.

That being said, this is an alternative method. In the original example, the host contract would send inline to the proxy contract using its own eosio.code permission level with a memo starting with the end user's account_name, then the proxy contract would remove the name from the memo, and create an account_name type to use in order to send an inline eosio::token, transfer to the end user with the edited memo. The action receivedTokens is passed a code param which is the contract that is hosting the token contract.

/**
 * Send inline action
 *
 * @brief Send inline action
 * @param CONTRACT - The account this action is intended for
 * @param NAME - The name of the action
 * @param ... - The member of the action specified as ("action_member1_name", action_member1_value)("action_member2_name", action_member2_value)
 */
#define SEND_INLINE_ACTION( CONTRACT, NAME, ... )\
INLINE_ACTION_SENDER(std::decay_t<decltype(CONTRACT)>, NAME)( (CONTRACT).get_self(),\
BOOST_PP_TUPLE_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)) );

Effectively the two contract's permission levels would not overlap and the separation between the contracts is to prevent the end user from occupying RAM in the host contract's tables. Here's a breakdown of the receivedTokens action in the proxy:

void receivedTokens( const currency::transfer& t, account_name code ) {
        if( t.to == _self ) { // checking if tokens were sent to proxy's contract name
            string cMemo = t.memo; // pulling memo
            string stringName(getAccountNameFromMemo(cMemo)); //extracting account name
            account_name to = string_to_name(stringName.c_str()); // assigning to type account_name
            string memo = cMemo.replace(0, cMemo.size() > stringName.size() ? stringName.size()+1 : stringName.size(), "");  // removing account name from memo to pass original memo
            INLINE_ACTION_SENDER(eosio::token, transfer)( code, {{_self,N(active)}}, {_self, to, t.quantity, memo} );
            //sending to "to" which was pulled from memo and using "t.quantity" which was passed from transfer effectively passing on all tokens
        }
    }

The original contract in the alternative example is sending both actions in this case because the active permission from the proxy contract is added to the host contract's eosio.code permission level.

On eosio.code from docs:

In order for an inline action to be sent from an account, add the eosio.code permission to the contract account's active permission. The eosio.code authority is a pseudo authority implemented to enhance security, and enable contracts to execute inline actions.

./cleos set account permission proxy_account active host_account eosio.code -p proxy_account@owner

Cleos command

This allows the host contract to perform an inline action to the proxy contract (using its own eosio.code permission level which it had to add to its active) and then another on behalf of the proxy's contract because "Proxy’s active would delegate to contract’s eosio.code" ... "but with a different auth". Now I believe by "a different auth" meaning the active permission level from the proxy's account added to the host account's eosio.code permission level for signing inline actions.

I think the code example he's referring to is this where there is a forward_auth param:

void forward( action_name reqauth, account_name forward_code, account_name forward_auth ) {
            require_auth( reqauth );
            INLINE_ACTION_SENDER(testinline, reqauth)( forward_code, {forward_auth,N(active)}, {forward_auth} );
         }

Link: https://github.com/EOSIO/eos/blob/905e7c85714aee4286fa180ce946f15ceb4ce73c/contracts/test.inline/test.inline.hpp

Also, I tried to compile the contract to test some things; however, the eosiolib is way out of date and those contracts are either not named that any more or are not included in the lib.

  • Thanks for the detailed explanatin! I was trying to dig a bit further when I found this PR. Looks like any evil smart contract can no longer consume RAM of the sender! – Vivek Kumar Dec 7 at 1:52

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.