|
1 |
| -/* |
2 |
| - Copyright 2016-2017 Nexus Development, LLC |
| 1 | +/// auth.sol -- widely-used access control pattern for Ethereum |
3 | 2 |
|
4 |
| - Licensed under the Apache License, Version 2.0 (the "License"); |
5 |
| - you may not use this file except in compliance with the License. |
6 |
| - You may obtain a copy of the License at |
| 3 | +// Copyright (C) 2015, 2016, 2017 Nexus Development, LLC |
7 | 4 |
|
8 |
| - http://www.apache.org/licenses/LICENSE-2.0 |
| 5 | +// Licensed under the Apache License, Version 2.0 (the "License"). |
| 6 | +// You may not use this file except in compliance with the License. |
9 | 7 |
|
10 |
| - Unless required by applicable law or agreed to in writing, software |
11 |
| - distributed under the License is distributed on an "AS IS" BASIS, |
12 |
| - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 |
| - See the License for the specific language governing permissions and |
14 |
| - limitations under the License. |
15 |
| -*/ |
| 8 | +// Unless required by applicable law or agreed to in writing, software |
| 9 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 10 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND (express or implied). |
16 | 11 |
|
17 | 12 | pragma solidity ^0.4.8;
|
18 | 13 |
|
19 |
| -contract DSAuthEvents { |
20 |
| - event LogSetAuthority (address indexed authority); |
21 |
| -} |
22 |
| - |
23 |
| -contract DSIAuth { |
24 |
| - function setAuthority(DSIAuthority newAuthority); |
25 |
| -} |
26 |
| - |
27 |
| -// `DSAuthority` is the interface which `DSAuth`-derived objects expect |
28 |
| -// their authority to be when it is defined. |
29 | 14 | contract DSIAuthority {
|
30 |
| - // `canCall` will be called with these arguments in the caller's |
31 |
| - // scope if it is coming from an `auth` check (`isAuthorized` internal function): |
32 |
| - // `DSAuthority(_ds_authority).canCall(msg.sender, address(this), msg.sig);` |
33 |
| - function canCall( address caller |
34 |
| - , address code |
35 |
| - , bytes4 sig ) |
36 |
| - constant |
37 |
| - returns (bool); |
| 15 | + function canCall( |
| 16 | + address src, address dst, bytes4 sig |
| 17 | + ) constant returns (bool); |
| 18 | +} |
38 | 19 |
|
39 |
| - function release(DSIAuth what); |
| 20 | +contract DSAuthEvents { |
| 21 | + event LogSetAuthority(address indexed authority); |
40 | 22 | }
|
41 | 23 |
|
42 |
| -contract DSAuth is DSIAuth, DSAuthEvents { |
| 24 | +contract DSAuth is DSAuthEvents { |
43 | 25 | DSIAuthority public authority;
|
44 | 26 |
|
45 | 27 | function DSAuth() {
|
46 | 28 | authority = DSIAuthority(msg.sender);
|
47 | 29 | LogSetAuthority(authority);
|
48 | 30 | }
|
49 | 31 |
|
50 |
| - function setAuthority(DSIAuthority newAuthority) |
| 32 | + function setAuthority(address authority_) |
51 | 33 | auth
|
52 | 34 | {
|
53 |
| - authority = newAuthority; |
| 35 | + authority = DSIAuthority(authority_); |
54 | 36 | LogSetAuthority(authority);
|
55 | 37 | }
|
56 | 38 |
|
57 | 39 | modifier auth {
|
58 |
| - if (!isAuthorized()) throw; |
| 40 | + assert(isAuthorized(msg.sender, msg.sig)); |
59 | 41 | _;
|
60 | 42 | }
|
61 | 43 |
|
62 |
| - function isAuthorized() internal returns (bool) |
63 |
| - { |
64 |
| - if ( address(authority) == msg.sender ) { |
| 44 | + modifier auth_as(string sig) { |
| 45 | + assert(isAuthorized(msg.sender, bytes4(sha3(sig)))); |
| 46 | + _; |
| 47 | + } |
| 48 | + |
| 49 | + function isAuthorized(address src, bytes4 sig) internal returns (bool) { |
| 50 | + if (src == address(authority)) { |
65 | 51 | return true;
|
66 |
| - } else if ( address(authority) == 0 ) { |
67 |
| - return false; |
68 | 52 | } else {
|
69 |
| - // WARNING, this must throw if calling empty code. This is only works |
70 |
| - // as of a recent compiler version. This is not clearly defined in |
71 |
| - // Solidity semantics so this behavior must have a dedicated test. |
72 |
| - return authority.canCall(msg.sender, this, msg.sig); |
| 53 | + // WARNING: |
| 54 | + // |
| 55 | + // This must throw if `authority' points to either (1) zero, |
| 56 | + // or (2) an address which has no code attached to it. |
| 57 | + // |
| 58 | + // This is not clearly defined in the semantics of Solidity |
| 59 | + // and only works as of a recent compiler version, so this |
| 60 | + // behavior must be tested explicitly. |
| 61 | + // |
| 62 | + return authority.canCall(src, this, sig); |
73 | 63 | }
|
74 | 64 | }
|
75 |
| -} |
76 | 65 |
|
77 |
| -// An DSIAuthority implementation with standard `release`. |
78 |
| -// TODO possible leave canCall undefined? |
79 |
| -contract DSAuthority is DSIAuthority |
80 |
| - , DSAuth |
81 |
| -{ |
82 |
| - // `canCall` will be called with these arguments in the caller's |
83 |
| - // scope if it is coming from an `auth` check (`isAuthorized` internal function): |
84 |
| - // `DSAuthority(_ds_authority).canCall(msg.sender, address(this), msg.sig);` |
85 |
| - function canCall( address caller |
86 |
| - , address code |
87 |
| - , bytes4 sig ) |
88 |
| - constant |
89 |
| - returns (bool) |
90 |
| - { |
91 |
| - return false; |
92 |
| - } |
93 |
| - |
94 |
| - function release(DSIAuth what) |
95 |
| - auth |
96 |
| - { |
97 |
| - what.setAuthority(DSIAuthority(msg.sender)); |
| 66 | + function assert(bool x) { |
| 67 | + if (!x) throw; |
98 | 68 | }
|
99 | 69 | }
|
100 |
| - |
0 commit comments