## Encumbered RAM proposal
gifted ram is added both to the `user_resources_table`, and to the new `gifted_ram` table described below.
### add a `gifted_ram` table
```c++
struct [[eosio::table, eosio::contract("eosio.system")]] gifted_ram {
name giftee;
name gifter;
int64_t ram_bytes = 0;
bool is_empty() const { return ram_bytes == 0; }
uint64_t primary_key() const { return giftee.value; } // unique as one giftee can only hold gifted ram from one gifter
};
typedef eosio::multi_index< "giftedram"_n, gifted_ram > gifted_ram_table;
```
This table will use a global scope of the `get_self()` account, and will not be scoped to the giftee (which we could do if we wanted to allow for multiple simultaneous gifters, but that would require also to maintain a total gift amount per giftee, and we don't feel that supporting multiple simultaneous gifters is required).
### new `giftram` action
```c++
// Transfers `ram_bytes` from `gifter` (`from`) to `giftee` (`to`), with the characteristic
// that the transfered ram is encumbered, meaning it can only be returned to
// the gifter via the `ungiftram` action. It cannot be traded, sold,
// re-gifted, or transfered otherwise. Its only use is for storing data.
// ----------------------------------------------------------------------------
//
// - requires that giftee does not hold gifted ram by someone else than gifter,
// as one account can only be hold gifted ram from one gifter at any time.
//
// - current gifter can gift additional ram to a giftee at any time (no restriction)
//
// - the fact of receiving gifted ram does not add any restriction to an
// account, besides the usage restictions on the gifted ram itself.
// For example, the account can purchase additional ram, and transfer,
// trade or sell this additional ram freely.
//
// - this will update both:
// a. the `gifted_ram` table to record the gift
// b. the `user_resources_table` to increase the usable ram
//
// - the ram cost of adding a row in the gifted_ram table will be incurred
// by the gifter.
// ----------------------------------------------------------------------------
[[eosio::action]] action_return_ramtransfer giftram(const name from, const name to, const int64_t ram_bytes, const std::string& memo );
```
where we re-use the return value `action_return_ramtransfer` defined as:
```c++
struct action_return_ramtransfer {
name from;
name to;
int64_t bytes;
int64_t from_ram_bytes;
int64_t to_ram_bytes;
};
```
### new `ungiftram` action
```c++
// returns all the gifted ram received by giftee (`from`) to `gifter` (`to`) (no fractional amount)
// ------------------------------------------------------------------------------------------------
//
// - specifying the gifter (`to` parameter) is not necessary as an account can only
// hold gifted ram from one gifter at any time
//
// - there is currently no built-in incentive for a giftee to return gifted ram.
//
// - if giftee account is found to hold gifted ram, and giftee has enough
// ram available to return the gift, this action will:
// a. transfer gifted ram back to gifter (full gifted amount)
// b. remove row from the gifted_ram table.
// c. unlock ram in the giftee's account equal to the overhead of
// removed row.
// d. decrease `ram_bytes` by the returned amount in `user_resources_table`
//
// - returned ram is unencumbered, which means there are no restrictions
// on its use.
// --------------------------------------------------------------------
[[eosio::action]] action_return_ramtransfer ungiftram(const name from, const name to, const std::string& memo );
```
### Changes in existing actions
Currently, when an account wants to do something with its ram (like sell it or transfer it), it calls `system_contract::reduce_ram()` which checks whether the account has enough ram available in its `user_resources_table`.
To take into account gifted ram, `reduce_ram` will be updated to disallow reducing the user `ram_bytes` below the gifted amount (read from the `gifted_ram` table).
When returning gifted ram, the `gifted_ram` row will be deleted before `reduce_ram` is called
The `add_ram` function does not have to be modified, and neither does `set_resource_ram_bytes_limits`.
`system_contract::update_user_resources` does not need to be updated either.
#### Change to `sellram` and `ramtransfer`, `buyram*`, `ramburn` actions
no change
## Test
command line test
```
cleos -u https://jungle4.cryptolions.io:443 push action eosio giftram {"from":"hokieshokies","to":"strangedays1","ram_bytes":100,"memo":"small ram gift"} -p hokieshokies@active
ungiftram(name from, name to, std::string memo );
cleos -u https://jungle4.cryptolions.io:443 push action eosio ungiftram {"from":"strangedays1","to":"hokieshokies","ram_bytes":50,"memo":"half back gift"} -p strangedays1@active
```