Skip to content
This repository has been archived by the owner on Jan 13, 2023. It is now read-only.

Commit

Permalink
add concluder contract
Browse files Browse the repository at this point in the history
  • Loading branch information
Brendan Chou committed Aug 21, 2019
1 parent 1a2364d commit dd3c3a1
Show file tree
Hide file tree
Showing 3 changed files with 535 additions and 93 deletions.
1 change: 1 addition & 0 deletions .soliumignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
contracts/external/traders/Expiry.sol
contracts/testing
contracts/Migrations.sol
150 changes: 57 additions & 93 deletions contracts/external/traders/Expiry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { Decimal } from "../../protocol/lib/Decimal.sol";
import { Math } from "../../protocol/lib/Math.sol";
import { Monetary } from "../../protocol/lib/Monetary.sol";
import { Require } from "../../protocol/lib/Require.sol";
import { Time } from "../../protocol/lib/Time.sol";
import { Types } from "../../protocol/lib/Types.sol";
import { OnlySolo } from "../helpers/OnlySolo.sol";

Expand All @@ -37,17 +36,15 @@ import { OnlySolo } from "../helpers/OnlySolo.sol";
* @title Expiry
* @author dYdX
*
* Sets the negative balance for an account to expire at a certain time. This allows any other
* account to repay that negative balance after expiry using any positive balance in the same
* account. The arbitrage incentive is the same as liquidation in the base protocol.
* Copy of Expiry contract that also allows approved senders to set expiry to be 28 days in the
* future.
*/
contract Expiry is
Ownable,
OnlySolo,
ICallee,
IAutoTrader
{
using SafeMath for uint32;
using SafeMath for uint256;
using Types for Types.Par;
using Types for Types.Wei;
Expand All @@ -56,23 +53,41 @@ contract Expiry is

bytes32 constant FILE = "Expiry";

uint256 constant FOUR_WEEKS_IN_SECONDS = 60 * 60 * 24 * 28;

// ============ Structs ============

struct ExpiryArg {
Account.Info account;
uint256 marketId;
}

// ============ Events ============

event ExpirySet(
address owner,
uint256 number,
uint256 marketId,
uint32 time
uint256 time
);

event LogExpiryRampTimeSet(
uint256 expiryRampTime
);

event LogSenderApproved(
address approver,
address sender,
bool approved
);

// ============ Storage ============

// owner => number => market => time
mapping (address => mapping (uint256 => mapping (uint256 => uint32))) g_expiries;
mapping (address => mapping (uint256 => mapping (uint256 => uint256))) g_expiries;

// owner => sender => approved
mapping (address => mapping (address => bool)) public g_approvedSender;

// time over which the liquidation ratio goes from zero to maximum
uint256 public g_expiryRampTime;
Expand Down Expand Up @@ -101,6 +116,18 @@ contract Expiry is
g_expiryRampTime = newExpiryRampTime;
}

// ============ Approval Functions ============

function approveSender(
address sender,
bool approved
)
external
{
emit LogSenderApproved(msg.sender, sender, approved);
g_approvedSender[msg.sender][sender] = approved;
}

// ============ Getters ============

function getExpiry(
Expand All @@ -109,15 +136,15 @@ contract Expiry is
)
public
view
returns (uint32)
returns (uint256)
{
return g_expiries[account.owner][account.number][marketId];
}

function getSpreadAdjustedPrices(
uint256 heldMarketId,
uint256 owedMarketId,
uint32 expiry
uint256 expiry
)
public
view
Expand All @@ -131,7 +158,7 @@ contract Expiry is
owedMarketId
);

uint256 expiryAge = Time.currentTime().sub(expiry);
uint256 expiryAge = block.timestamp.sub(expiry);

if (expiryAge < g_expiryRampTime) {
spread.value = Math.getPartial(spread.value, expiryAge, g_expiryRampTime);
Expand All @@ -154,17 +181,21 @@ contract Expiry is
public
onlySolo(msg.sender)
{
(
uint256 marketId,
uint32 expiryTime
) = parseCallArgs(data);
ExpiryArg[] memory expiries = abi.decode(data, (ExpiryArg[]));

// don't set expiry time for accounts with positive balance
if (expiryTime != 0 && !SOLO_MARGIN.getAccountPar(account, marketId).isNegative()) {
return;
for (uint256 i = 0; i < expiries.length; i++) {
ExpiryArg memory exp = expiries[i];
Require.that(
g_approvedSender[exp.account.owner][account.owner],
FILE,
"Unapproved sender"
);
Types.Par memory par = SOLO_MARGIN.getAccountPar(exp.account, exp.marketId);
uint256 expiryTime = par.isNegative()
? block.timestamp.add(FOUR_WEEKS_IN_SECONDS)
: 0;
setExpiry(exp.account, exp.marketId, expiryTime);
}

setExpiry(account, marketId, expiryTime);
}

function getTradeCost(
Expand All @@ -191,12 +222,9 @@ contract Expiry is
});
}

(
uint256 owedMarketId,
uint32 maxExpiry
) = parseTradeArgs(data);
(uint256 owedMarketId, uint256 maxExpiry) = abi.decode(data, (uint256, uint256));

uint32 expiry = getExpiry(makerAccount, owedMarketId);
uint256 expiry = getExpiry(makerAccount, owedMarketId);

// validate expiry
Require.that(
Expand All @@ -208,7 +236,7 @@ contract Expiry is
owedMarketId
);
Require.that(
expiry <= Time.currentTime(),
expiry <= block.timestamp,
FILE,
"Borrow not yet expired",
expiry
Expand Down Expand Up @@ -242,7 +270,7 @@ contract Expiry is
Types.Par memory newInputPar,
Types.Wei memory inputWei,
uint256 owedMarketId,
uint32 expiry
uint256 expiry
)
private
returns (Types.AssetAmount memory)
Expand Down Expand Up @@ -331,7 +359,7 @@ contract Expiry is
function setExpiry(
Account.Info memory account,
uint256 marketId,
uint32 time
uint256 time
)
private
{
Expand All @@ -349,7 +377,7 @@ contract Expiry is
Types.Wei memory heldWei,
uint256 heldMarketId,
uint256 owedMarketId,
uint32 expiry
uint256 expiry
)
private
view
Expand Down Expand Up @@ -382,7 +410,7 @@ contract Expiry is
Types.Wei memory owedWei,
uint256 heldMarketId,
uint256 owedMarketId,
uint32 expiry
uint256 expiry
)
private
view
Expand Down Expand Up @@ -410,68 +438,4 @@ contract Expiry is
value: heldAmount
});
}

function parseCallArgs(
bytes memory data
)
private
pure
returns (
uint256,
uint32
)
{
Require.that(
data.length == 64,
FILE,
"Call data invalid length",
data.length
);

uint256 marketId;
uint256 rawExpiry;

/* solium-disable-next-line security/no-inline-assembly */
assembly {
marketId := mload(add(data, 32))
rawExpiry := mload(add(data, 64))
}

return (
marketId,
Math.to32(rawExpiry)
);
}

function parseTradeArgs(
bytes memory data
)
private
pure
returns (
uint256,
uint32
)
{
Require.that(
data.length == 64,
FILE,
"Trade data invalid length",
data.length
);

uint256 owedMarketId;
uint256 rawExpiry;

/* solium-disable-next-line security/no-inline-assembly */
assembly {
owedMarketId := mload(add(data, 32))
rawExpiry := mload(add(data, 64))
}

return (
owedMarketId,
Math.to32(rawExpiry)
);
}
}
Loading

0 comments on commit dd3c3a1

Please sign in to comment.