diff --git a/actors/builtin/market/cbor_gen.go b/actors/builtin/market/cbor_gen.go
index 4ed5bd11c..a459c7830 100644
--- a/actors/builtin/market/cbor_gen.go
+++ b/actors/builtin/market/cbor_gen.go
@@ -398,3 +398,386 @@ func (t *DealState) UnmarshalCBOR(r io.Reader) error {
 	}
 	return nil
 }
+
+var lengthBufActivateDealsParams = []byte{129}
+
+func (t *ActivateDealsParams) MarshalCBOR(w io.Writer) error {
+	if t == nil {
+		_, err := w.Write(cbg.CborNull)
+		return err
+	}
+	if _, err := w.Write(lengthBufActivateDealsParams); err != nil {
+		return err
+	}
+
+	scratch := make([]byte, 9)
+
+	// t.Sectors ([]market.ActivateDealsParamsInner) (slice)
+	if len(t.Sectors) > cbg.MaxLength {
+		return xerrors.Errorf("Slice value in field t.Sectors was too long")
+	}
+
+	if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Sectors))); err != nil {
+		return err
+	}
+	for _, v := range t.Sectors {
+		if err := v.MarshalCBOR(w); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (t *ActivateDealsParams) UnmarshalCBOR(r io.Reader) error {
+	*t = ActivateDealsParams{}
+
+	br := cbg.GetPeeker(r)
+	scratch := make([]byte, 8)
+
+	maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+	if maj != cbg.MajArray {
+		return fmt.Errorf("cbor input should be of type array")
+	}
+
+	if extra != 1 {
+		return fmt.Errorf("cbor input had wrong number of fields")
+	}
+
+	// t.Sectors ([]market.ActivateDealsParamsInner) (slice)
+
+	maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+
+	if extra > cbg.MaxLength {
+		return fmt.Errorf("t.Sectors: array too large (%d)", extra)
+	}
+
+	if maj != cbg.MajArray {
+		return fmt.Errorf("expected cbor array")
+	}
+
+	if extra > 0 {
+		t.Sectors = make([]ActivateDealsParamsInner, extra)
+	}
+
+	for i := 0; i < int(extra); i++ {
+
+		var v ActivateDealsParamsInner
+		if err := v.UnmarshalCBOR(br); err != nil {
+			return err
+		}
+
+		t.Sectors[i] = v
+	}
+
+	return nil
+}
+
+var lengthBufActivateDealsParamsInner = []byte{130}
+
+func (t *ActivateDealsParamsInner) MarshalCBOR(w io.Writer) error {
+	if t == nil {
+		_, err := w.Write(cbg.CborNull)
+		return err
+	}
+	if _, err := w.Write(lengthBufActivateDealsParamsInner); err != nil {
+		return err
+	}
+
+	scratch := make([]byte, 9)
+
+	// t.DealIDs ([]abi.DealID) (slice)
+	if len(t.DealIDs) > cbg.MaxLength {
+		return xerrors.Errorf("Slice value in field t.DealIDs was too long")
+	}
+
+	if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.DealIDs))); err != nil {
+		return err
+	}
+	for _, v := range t.DealIDs {
+		if err := cbg.CborWriteHeader(w, cbg.MajUnsignedInt, uint64(v)); err != nil {
+			return err
+		}
+	}
+
+	// t.SectorExpiry (abi.ChainEpoch) (int64)
+	if t.SectorExpiry >= 0 {
+		if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.SectorExpiry)); err != nil {
+			return err
+		}
+	} else {
+		if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.SectorExpiry-1)); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (t *ActivateDealsParamsInner) UnmarshalCBOR(r io.Reader) error {
+	*t = ActivateDealsParamsInner{}
+
+	br := cbg.GetPeeker(r)
+	scratch := make([]byte, 8)
+
+	maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+	if maj != cbg.MajArray {
+		return fmt.Errorf("cbor input should be of type array")
+	}
+
+	if extra != 2 {
+		return fmt.Errorf("cbor input had wrong number of fields")
+	}
+
+	// t.DealIDs ([]abi.DealID) (slice)
+
+	maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+
+	if extra > cbg.MaxLength {
+		return fmt.Errorf("t.DealIDs: array too large (%d)", extra)
+	}
+
+	if maj != cbg.MajArray {
+		return fmt.Errorf("expected cbor array")
+	}
+
+	if extra > 0 {
+		t.DealIDs = make([]abi.DealID, extra)
+	}
+
+	for i := 0; i < int(extra); i++ {
+
+		maj, val, err := cbg.CborReadHeaderBuf(br, scratch)
+		if err != nil {
+			return xerrors.Errorf("failed to read uint64 for t.DealIDs slice: %w", err)
+		}
+
+		if maj != cbg.MajUnsignedInt {
+			return xerrors.Errorf("value read for array t.DealIDs was not a uint, instead got %d", maj)
+		}
+
+		t.DealIDs[i] = abi.DealID(val)
+	}
+
+	// t.SectorExpiry (abi.ChainEpoch) (int64)
+	{
+		maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
+		var extraI int64
+		if err != nil {
+			return err
+		}
+		switch maj {
+		case cbg.MajUnsignedInt:
+			extraI = int64(extra)
+			if extraI < 0 {
+				return fmt.Errorf("int64 positive overflow")
+			}
+		case cbg.MajNegativeInt:
+			extraI = int64(extra)
+			if extraI < 0 {
+				return fmt.Errorf("int64 negative oveflow")
+			}
+			extraI = -1 - extraI
+		default:
+			return fmt.Errorf("wrong type for int64 field: %d", maj)
+		}
+
+		t.SectorExpiry = abi.ChainEpoch(extraI)
+	}
+	return nil
+}
+
+var lengthBufActivateDealsReturn = []byte{129}
+
+func (t *ActivateDealsReturn) MarshalCBOR(w io.Writer) error {
+	if t == nil {
+		_, err := w.Write(cbg.CborNull)
+		return err
+	}
+	if _, err := w.Write(lengthBufActivateDealsReturn); err != nil {
+		return err
+	}
+
+	scratch := make([]byte, 9)
+
+	// t.Sectors ([]market.ActivateDealsReturnInner) (slice)
+	if len(t.Sectors) > cbg.MaxLength {
+		return xerrors.Errorf("Slice value in field t.Sectors was too long")
+	}
+
+	if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Sectors))); err != nil {
+		return err
+	}
+	for _, v := range t.Sectors {
+		if err := v.MarshalCBOR(w); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (t *ActivateDealsReturn) UnmarshalCBOR(r io.Reader) error {
+	*t = ActivateDealsReturn{}
+
+	br := cbg.GetPeeker(r)
+	scratch := make([]byte, 8)
+
+	maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+	if maj != cbg.MajArray {
+		return fmt.Errorf("cbor input should be of type array")
+	}
+
+	if extra != 1 {
+		return fmt.Errorf("cbor input had wrong number of fields")
+	}
+
+	// t.Sectors ([]market.ActivateDealsReturnInner) (slice)
+
+	maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+
+	if extra > cbg.MaxLength {
+		return fmt.Errorf("t.Sectors: array too large (%d)", extra)
+	}
+
+	if maj != cbg.MajArray {
+		return fmt.Errorf("expected cbor array")
+	}
+
+	if extra > 0 {
+		t.Sectors = make([]ActivateDealsReturnInner, extra)
+	}
+
+	for i := 0; i < int(extra); i++ {
+
+		var v ActivateDealsReturnInner
+		if err := v.UnmarshalCBOR(br); err != nil {
+			return err
+		}
+
+		t.Sectors[i] = v
+	}
+
+	return nil
+}
+
+var lengthBufActivateDealsReturnInner = []byte{132}
+
+func (t *ActivateDealsReturnInner) MarshalCBOR(w io.Writer) error {
+	if t == nil {
+		_, err := w.Write(cbg.CborNull)
+		return err
+	}
+	if _, err := w.Write(lengthBufActivateDealsReturnInner); err != nil {
+		return err
+	}
+
+	scratch := make([]byte, 9)
+
+	// t.Success (bool) (bool)
+	if err := cbg.WriteBool(w, t.Success); err != nil {
+		return err
+	}
+
+	// t.DealSpace (uint64) (uint64)
+
+	if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.DealSpace)); err != nil {
+		return err
+	}
+
+	// t.DealWeight (big.Int) (struct)
+	if err := t.DealWeight.MarshalCBOR(w); err != nil {
+		return err
+	}
+
+	// t.VerifiedDealWeight (big.Int) (struct)
+	if err := t.VerifiedDealWeight.MarshalCBOR(w); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (t *ActivateDealsReturnInner) UnmarshalCBOR(r io.Reader) error {
+	*t = ActivateDealsReturnInner{}
+
+	br := cbg.GetPeeker(r)
+	scratch := make([]byte, 8)
+
+	maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+	if maj != cbg.MajArray {
+		return fmt.Errorf("cbor input should be of type array")
+	}
+
+	if extra != 4 {
+		return fmt.Errorf("cbor input had wrong number of fields")
+	}
+
+	// t.Success (bool) (bool)
+
+	maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
+	if err != nil {
+		return err
+	}
+	if maj != cbg.MajOther {
+		return fmt.Errorf("booleans must be major type 7")
+	}
+	switch extra {
+	case 20:
+		t.Success = false
+	case 21:
+		t.Success = true
+	default:
+		return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
+	}
+	// t.DealSpace (uint64) (uint64)
+
+	{
+
+		maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
+		if err != nil {
+			return err
+		}
+		if maj != cbg.MajUnsignedInt {
+			return fmt.Errorf("wrong type for uint64 field")
+		}
+		t.DealSpace = uint64(extra)
+
+	}
+	// t.DealWeight (big.Int) (struct)
+
+	{
+
+		if err := t.DealWeight.UnmarshalCBOR(br); err != nil {
+			return xerrors.Errorf("unmarshaling t.DealWeight: %w", err)
+		}
+
+	}
+	// t.VerifiedDealWeight (big.Int) (struct)
+
+	{
+
+		if err := t.VerifiedDealWeight.UnmarshalCBOR(br); err != nil {
+			return xerrors.Errorf("unmarshaling t.VerifiedDealWeight: %w", err)
+		}
+
+	}
+	return nil
+}
diff --git a/actors/builtin/market/market_actor.go b/actors/builtin/market/market_actor.go
index 116277297..edd9015cd 100644
--- a/actors/builtin/market/market_actor.go
+++ b/actors/builtin/market/market_actor.go
@@ -406,15 +406,32 @@ func (a Actor) VerifyDealsForActivation(rt Runtime, params *VerifyDealsForActiva
 	}
 }
 
-//type ActivateDealsParams struct {
-//	DealIDs      []abi.DealID
-//	SectorExpiry abi.ChainEpoch
-//}
-type ActivateDealsParams = market0.ActivateDealsParams
+type ActivateDealsParams struct {
+	Sectors []ActivateDealsParamsInner
+}
+
+//cbor-gen is annoying
+type ActivateDealsParamsInner struct {
+	DealIDs      []abi.DealID
+	SectorExpiry abi.ChainEpoch
+}
+
+type ActivateDealsReturn struct {
+	Sectors []ActivateDealsReturnInner
+}
+
+type ActivateDealsReturnInner struct {
+	Success            bool           // True if activation was a success
+	DealSpace          uint64         // Total space in bytes of submitted deals.
+	DealWeight         abi.DealWeight // Total space*time of submitted deals.
+	VerifiedDealWeight abi.DealWeight // Total space*time of submitted verified deals.
+}
 
 // Verify that a given set of storage deals is valid for a sector currently being ProveCommitted,
 // update the market's internal state accordingly.
-func (a Actor) ActivateDeals(rt Runtime, params *ActivateDealsParams) *abi.EmptyValue {
+// TODO: ActivateDeals somehow needs to check DealSpace <= SectorSize
+// currently it was done at precommit
+func (a Actor) ActivateDeals(rt Runtime, params *ActivateDealsParams) *ActivateDealsReturn {
 	rt.ValidateImmediateCallerType(builtin.StorageMinerActorCodeID)
 	minerAddr := rt.Caller()
 	currEpoch := rt.CurrEpoch()
@@ -422,50 +439,83 @@ func (a Actor) ActivateDeals(rt Runtime, params *ActivateDealsParams) *abi.Empty
 	var st State
 	store := adt.AsStore(rt)
 
+	res := make([]ActivateDealsReturnInner, len(params.Sectors))
+
 	// Update deal dealStates.
 	rt.StateTransaction(&st, func() {
-		_, _, _, err := ValidateDealsForActivation(&st, store, params.DealIDs, minerAddr, params.SectorExpiry, currEpoch)
-		builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to validate dealProposals for activation")
-
-		msm, err := st.mutator(adt.AsStore(rt)).withDealStates(WritePermission).
-			withPendingProposals(ReadOnlyPermission).withDealProposals(ReadOnlyPermission).build()
-		builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load state")
 
-		for _, dealID := range params.DealIDs {
-			// This construction could be replaced with a single "update deal state" state method, possibly batched
-			// over all deal ids at once.
-			_, found, err := msm.dealStates.Get(dealID)
-			builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get state for dealId %d", dealID)
-			if found {
-				rt.Abortf(exitcode.ErrIllegalArgument, "deal %d already included in another sector", dealID)
+	outer:
+		for i, sector := range params.Sectors {
+			dealWeight, verifiedWeight, dealSpace, err := ValidateDealsForActivation(&st, store, sector.DealIDs, minerAddr, sector.SectorExpiry, currEpoch)
+			//builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to validate dealProposals for activation")
+			if err != nil {
+				continue outer
 			}
 
-			proposal, err := getDealProposal(msm.dealProposals, dealID)
-			builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get dealId %d", dealID)
+			msm, err := st.mutator(adt.AsStore(rt)).withDealStates(WritePermission).
+				withPendingProposals(ReadOnlyPermission).withDealProposals(ReadOnlyPermission).build()
+			builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load state")
+
+			for _, dealID := range sector.DealIDs {
+				// This construction could be replaced with a single "update deal state" state method, possibly batched
+				// over all deal ids at once.
+				_, found, err := msm.dealStates.Get(dealID)
+				//builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get state for dealId %d", dealID)
+				if err != nil {
+					continue outer
+				}
 
-			propc, err := proposal.Cid()
-			builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to calculate proposal CID")
+				if found {
+					//rt.Abortf(exitcode.ErrIllegalArgument, "deal %d already included in another sector", dealID)
+					if err != nil {
+						continue outer
+					}
+				}
+
+				proposal, err := getDealProposal(msm.dealProposals, dealID)
+				//builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get dealId %d", dealID)
+				if err != nil {
+					continue outer
+				}
+
+				propc, err := proposal.Cid()
+				//builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to calculate proposal CID")
+				if err != nil {
+					continue outer
+				}
+
+				has, err := msm.pendingDeals.Has(abi.CidKey(propc))
+				//builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get pending proposal %v", propc)
+				if err != nil {
+					continue outer
+				}
 
-			has, err := msm.pendingDeals.Has(abi.CidKey(propc))
-			builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get pending proposal %v", propc)
+				if !has {
+					//	rt.Abortf(exitcode.ErrIllegalState, "tried to activate deal that was not in the pending set (%s)", propc)
+					continue outer
+				}
 
-			if !has {
-				rt.Abortf(exitcode.ErrIllegalState, "tried to activate deal that was not in the pending set (%s)", propc)
+				err = msm.dealStates.Set(dealID, &DealState{
+					SectorStartEpoch: currEpoch,
+					LastUpdatedEpoch: epochUndefined,
+					SlashEpoch:       epochUndefined,
+				})
+				builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to set deal state %d", dealID)
 			}
 
-			err = msm.dealStates.Set(dealID, &DealState{
-				SectorStartEpoch: currEpoch,
-				LastUpdatedEpoch: epochUndefined,
-				SlashEpoch:       epochUndefined,
-			})
-			builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to set deal state %d", dealID)
-		}
+			res[i] = ActivateDealsReturnInner{
+				Success:            true,
+				DealSpace:          dealSpace,
+				DealWeight:         dealWeight,
+				VerifiedDealWeight: verifiedWeight,
+			}
 
-		err = msm.commitState()
-		builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush state")
+			err = msm.commitState()
+			builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush state")
+		}
 	})
 
-	return nil
+	return &ActivateDealsReturn{Sectors: res}
 }
 
 //type SectorDataSpec struct {
diff --git a/actors/builtin/methods.go b/actors/builtin/methods.go
index bbb4f2d3f..0657f87d8 100644
--- a/actors/builtin/methods.go
+++ b/actors/builtin/methods.go
@@ -103,7 +103,8 @@ var MethodsMiner = struct {
 	PreCommitSectorBatch     abi.MethodNum
 	ProveCommitAggregate     abi.MethodNum
 	ProveReplicaUpdates      abi.MethodNum
-}{MethodConstructor, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}
+	PreCommitSectorBatch2    abi.MethodNum
+}{MethodConstructor, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}
 
 var MethodsVerifiedRegistry = struct {
 	Constructor                 abi.MethodNum
diff --git a/actors/builtin/miner/cbor_gen.go b/actors/builtin/miner/cbor_gen.go
index b2972b9f1..5d4fc3fb4 100644
--- a/actors/builtin/miner/cbor_gen.go
+++ b/actors/builtin/miner/cbor_gen.go
@@ -1367,7 +1367,7 @@ func (t *PowerPair) UnmarshalCBOR(r io.Reader) error {
 	return nil
 }
 
-var lengthBufSectorPreCommitOnChainInfo = []byte{133}
+var lengthBufSectorPreCommitOnChainInfo = []byte{131}
 
 func (t *SectorPreCommitOnChainInfo) MarshalCBOR(w io.Writer) error {
 	if t == nil {
@@ -1400,16 +1400,6 @@ func (t *SectorPreCommitOnChainInfo) MarshalCBOR(w io.Writer) error {
 			return err
 		}
 	}
-
-	// t.DealWeight (big.Int) (struct)
-	if err := t.DealWeight.MarshalCBOR(w); err != nil {
-		return err
-	}
-
-	// t.VerifiedDealWeight (big.Int) (struct)
-	if err := t.VerifiedDealWeight.MarshalCBOR(w); err != nil {
-		return err
-	}
 	return nil
 }
 
@@ -1427,7 +1417,7 @@ func (t *SectorPreCommitOnChainInfo) UnmarshalCBOR(r io.Reader) error {
 		return fmt.Errorf("cbor input should be of type array")
 	}
 
-	if extra != 5 {
+	if extra != 3 {
 		return fmt.Errorf("cbor input had wrong number of fields")
 	}
 
@@ -1474,28 +1464,10 @@ func (t *SectorPreCommitOnChainInfo) UnmarshalCBOR(r io.Reader) error {
 
 		t.PreCommitEpoch = abi.ChainEpoch(extraI)
 	}
-	// t.DealWeight (big.Int) (struct)
-
-	{
-
-		if err := t.DealWeight.UnmarshalCBOR(br); err != nil {
-			return xerrors.Errorf("unmarshaling t.DealWeight: %w", err)
-		}
-
-	}
-	// t.VerifiedDealWeight (big.Int) (struct)
-
-	{
-
-		if err := t.VerifiedDealWeight.UnmarshalCBOR(br); err != nil {
-			return xerrors.Errorf("unmarshaling t.VerifiedDealWeight: %w", err)
-		}
-
-	}
 	return nil
 }
 
-var lengthBufSectorPreCommitInfo = []byte{138}
+var lengthBufSectorPreCommitInfo = []byte{135}
 
 func (t *SectorPreCommitInfo) MarshalCBOR(w io.Writer) error {
 	if t == nil {
@@ -1567,27 +1539,16 @@ func (t *SectorPreCommitInfo) MarshalCBOR(w io.Writer) error {
 		}
 	}
 
-	// t.ReplaceCapacity (bool) (bool)
-	if err := cbg.WriteBool(w, t.ReplaceCapacity); err != nil {
-		return err
-	}
-
-	// t.ReplaceSectorDeadline (uint64) (uint64)
-
-	if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.ReplaceSectorDeadline)); err != nil {
-		return err
-	}
-
-	// t.ReplaceSectorPartition (uint64) (uint64)
+	// t.UnsealedCID (cid.Cid) (struct)
 
-	if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.ReplaceSectorPartition)); err != nil {
-		return err
-	}
-
-	// t.ReplaceSectorNumber (abi.SectorNumber) (uint64)
-
-	if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.ReplaceSectorNumber)); err != nil {
-		return err
+	if t.UnsealedCID == nil {
+		if _, err := w.Write(cbg.CborNull); err != nil {
+			return err
+		}
+	} else {
+		if err := cbg.WriteCidBuf(scratch, w, *t.UnsealedCID); err != nil {
+			return xerrors.Errorf("failed to write cid field t.UnsealedCID: %w", err)
+		}
 	}
 
 	return nil
@@ -1607,7 +1568,7 @@ func (t *SectorPreCommitInfo) UnmarshalCBOR(r io.Reader) error {
 		return fmt.Errorf("cbor input should be of type array")
 	}
 
-	if extra != 10 {
+	if extra != 7 {
 		return fmt.Errorf("cbor input had wrong number of fields")
 	}
 
@@ -1745,63 +1706,26 @@ func (t *SectorPreCommitInfo) UnmarshalCBOR(r io.Reader) error {
 
 		t.Expiration = abi.ChainEpoch(extraI)
 	}
-	// t.ReplaceCapacity (bool) (bool)
-
-	maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
-	if err != nil {
-		return err
-	}
-	if maj != cbg.MajOther {
-		return fmt.Errorf("booleans must be major type 7")
-	}
-	switch extra {
-	case 20:
-		t.ReplaceCapacity = false
-	case 21:
-		t.ReplaceCapacity = true
-	default:
-		return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra)
-	}
-	// t.ReplaceSectorDeadline (uint64) (uint64)
+	// t.UnsealedCID (cid.Cid) (struct)
 
 	{
 
-		maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
-		if err != nil {
-			return err
-		}
-		if maj != cbg.MajUnsignedInt {
-			return fmt.Errorf("wrong type for uint64 field")
-		}
-		t.ReplaceSectorDeadline = uint64(extra)
-
-	}
-	// t.ReplaceSectorPartition (uint64) (uint64)
-
-	{
-
-		maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
+		b, err := br.ReadByte()
 		if err != nil {
 			return err
 		}
-		if maj != cbg.MajUnsignedInt {
-			return fmt.Errorf("wrong type for uint64 field")
-		}
-		t.ReplaceSectorPartition = uint64(extra)
-
-	}
-	// t.ReplaceSectorNumber (abi.SectorNumber) (uint64)
+		if b != cbg.CborNull[0] {
+			if err := br.UnreadByte(); err != nil {
+				return err
+			}
 
-	{
+			c, err := cbg.ReadCid(br)
+			if err != nil {
+				return xerrors.Errorf("failed to read cid field t.UnsealedCID: %w", err)
+			}
 
-		maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
-		if err != nil {
-			return err
-		}
-		if maj != cbg.MajUnsignedInt {
-			return fmt.Errorf("wrong type for uint64 field")
+			t.UnsealedCID = &c
 		}
-		t.ReplaceSectorNumber = abi.SectorNumber(extra)
 
 	}
 	return nil
diff --git a/actors/builtin/miner/miner_actor.go b/actors/builtin/miner/miner_actor.go
index a7c0edefd..7e2bda02d 100644
--- a/actors/builtin/miner/miner_actor.go
+++ b/actors/builtin/miner/miner_actor.go
@@ -78,6 +78,7 @@ func (a Actor) Exports() []interface{} {
 		25:                        a.PreCommitSectorBatch,
 		26:                        a.ProveCommitAggregate,
 		27:                        a.ProveReplicaUpdates,
+		28:                        a.PreCommitSectorBatch2,
 	}
 }
 
@@ -676,6 +677,40 @@ type PreCommitSectorBatchParams = miner5.PreCommitSectorBatchParams
 // This method calculates the sector's power, locks a pre-commit deposit for the sector, stores information about the
 // sector in state and waits for it to be proven or expire.
 func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchParams) *abi.EmptyValue {
+	newSectors := make([]SectorPreCommitInfo, 0, len(params.Sectors))
+	for _, pi := range params.Sectors {
+		if pi.ReplaceCapacity {
+			rt.Abortf(exitcode.SysErrForbidden, "cc upgrade through precommit discontinued, use lightweight cc upgrade instead")
+		}
+		newSectors = append(newSectors, SectorPreCommitInfo{
+			SealProof:     pi.SealProof,
+			SectorNumber:  pi.SectorNumber,
+			SealedCID:     pi.SealedCID,
+			SealRandEpoch: pi.SealRandEpoch,
+			DealIDs:       pi.DealIDs,
+			Expiration:    pi.Expiration,
+			UnsealedCID:   nil,
+		})
+	}
+
+	return a.preCommitSectorBatch2Inner(rt, &PreCommitSectorBatch2Params{Sectors: newSectors}, false)
+}
+
+type PreCommitSectorBatch2Params struct {
+	Sectors []SectorPreCommitInfo
+}
+
+// Pledges the miner to seal and commit some new sectors.
+// The caller specifies sector numbers, sealed sector data CIDs, seal randomness epoch, expiration, UnsealedCID, and the IDs
+// of any storage deals contained in the sector data. The storage deal proposals should be already submitted
+// to the storage market actor.
+// This method assumes maximum sector power, locks a pre-commit deposit for the sector, stores information about the
+// sector in state and waits for it to be proven or expire.
+func (a Actor) PreCommitSectorBatch2(rt Runtime, params *PreCommitSectorBatch2Params) *abi.EmptyValue {
+	return a.preCommitSectorBatch2Inner(rt, params, true)
+}
+
+func (a Actor) preCommitSectorBatch2Inner(rt Runtime, params *PreCommitSectorBatch2Params, newBehaviour bool) *abi.EmptyValue {
 	currEpoch := rt.CurrEpoch()
 	if len(params.Sectors) == 0 {
 		rt.Abortf(exitcode.ErrIllegalArgument, "batch empty")
@@ -685,9 +720,9 @@ func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchPara
 
 	// Check per-sector preconditions before opening state transaction or sending other messages.
 	challengeEarliest := currEpoch - MaxPreCommitRandomnessLookback
-	sectorsDeals := make([]market.SectorDeals, len(params.Sectors))
+	sectorsDeals := make([]market.SectorDeals, 0)
 	sectorNumbers := bitfield.New()
-	for i, precommit := range params.Sectors {
+	for _, precommit := range params.Sectors {
 		// Bitfied.IsSet() is fast when there are only locally-set values.
 		set, err := sectorNumbers.IsSet(uint64(precommit.SectorNumber))
 		builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "error checking sector number")
@@ -714,30 +749,40 @@ func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchPara
 		if precommit.SealRandEpoch < challengeEarliest {
 			rt.Abortf(exitcode.ErrIllegalArgument, "seal challenge epoch %v too old, must be after %v", precommit.SealRandEpoch, challengeEarliest)
 		}
+		if precommit.UnsealedCID != nil {
+			if !precommit.UnsealedCID.Defined() {
+				rt.Abortf(exitcode.ErrIllegalArgument, "unsealed CID undefined")
+			}
+			if precommit.UnsealedCID.Prefix() != market.PieceCIDPrefix {
+				rt.Abortf(exitcode.ErrIllegalArgument, "unsealed CID had wrong prefix")
+			}
+			if len(precommit.DealIDs) == 0 {
+				rt.Abortf(exitcode.ErrIllegalArgument, "UnsealedCID passed when there are no deals")
+			}
+		} else {
+			if newBehaviour && (len(precommit.DealIDs) > 0) {
+				rt.Abortf(exitcode.ErrIllegalArgument, "UnsealedCID missing when there are deals")
+			}
+		}
 
 		// Require sector lifetime meets minimum by assuming activation happens at last epoch permitted for seal proof.
 		// This could make sector maximum lifetime validation more lenient if the maximum sector limit isn't hit first.
 		maxActivation := currEpoch + MaxProveCommitDuration[precommit.SealProof]
 		validateExpiration(rt, maxActivation, precommit.Expiration, precommit.SealProof)
-
-		if precommit.ReplaceCapacity {
-			rt.Abortf(exitcode.SysErrForbidden, "cc upgrade through precommit discontinued, use lightweight cc upgrade instead")
-		}
-
-		sectorsDeals[i] = market.SectorDeals{
-			SectorExpiry: precommit.Expiration,
-			DealIDs:      precommit.DealIDs,
+		if len(precommit.DealIDs) > 0 {
+			sectorsDeals = append(sectorsDeals, market.SectorDeals{
+				SectorExpiry: precommit.Expiration,
+				DealIDs:      precommit.DealIDs,
+			})
 		}
 	}
 
 	// gather information from other actors
 	rewardStats := requestCurrentEpochBlockReward(rt)
 	pwrTotal := requestCurrentTotalPower(rt)
-	dealWeights := requestDealWeights(rt, sectorsDeals)
 
-	if len(dealWeights.Sectors) != len(params.Sectors) {
-		rt.Abortf(exitcode.ErrIllegalState, "deal weight request returned %d records, expected %d",
-			len(dealWeights.Sectors), len(params.Sectors))
+	if !newBehaviour && len(sectorsDeals) > 0 {
+		verifyDealsForActivation(rt, sectorsDeals)
 	}
 
 	store := adt.AsStore(rt)
@@ -785,26 +830,15 @@ func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchPara
 				rt.Abortf(exitcode.ErrIllegalArgument, "too many deals for sector %d > %d", len(precommit.DealIDs), dealCountMax)
 			}
 
-			// Ensure total deal space does not exceed sector size.
-			dealWeight := dealWeights.Sectors[i]
-			if dealWeight.DealSpace > uint64(info.SectorSize) {
-				rt.Abortf(exitcode.ErrIllegalArgument, "deals too large to fit in sector %d > %d", dealWeight.DealSpace, info.SectorSize)
-			}
-
-			// Estimate the sector weight using the current epoch as an estimate for activation,
-			// and compute the pre-commit deposit using that weight.
-			// The sector's power will be recalculated when it's proven.
-			duration := precommit.Expiration - currEpoch
-			sectorWeight := QAPowerForWeight(info.SectorSize, duration, dealWeight.DealWeight, dealWeight.VerifiedDealWeight)
+			// For PreCommitDeposit we estimate maximum possible power of the sector
+			sectorWeight := QAPowerMax(info.SectorSize)
 			depositReq := PreCommitDepositForPower(rewardStats.ThisEpochRewardSmoothed, pwrTotal.QualityAdjPowerSmoothed, sectorWeight)
 
 			// Build on-chain record.
 			chainInfos[i] = &SectorPreCommitOnChainInfo{
-				Info:               SectorPreCommitInfo(precommit),
-				PreCommitDeposit:   depositReq,
-				PreCommitEpoch:     currEpoch,
-				DealWeight:         dealWeight.DealWeight,
-				VerifiedDealWeight: dealWeight.VerifiedDealWeight,
+				Info:             SectorPreCommitInfo(precommit),
+				PreCommitDeposit: depositReq,
+				PreCommitEpoch:   currEpoch,
 			}
 			totalDepositRequired = big.Add(totalDepositRequired, depositReq)
 
@@ -916,6 +950,18 @@ func (a Actor) ProveCommitAggregate(rt Runtime, params *ProveCommitAggregatePara
 
 	// compute shared verification inputs
 	commDs := requestUnsealedSectorCIDs(rt, computeDataCommitmentsInputs...)
+	for i, precommit := range precommits {
+		if len(precommit.Info.DealIDs) > 0 {
+			if precommit.Info.UnsealedCID != nil {
+				// new precommit
+				if !precommit.Info.UnsealedCID.Equals(commDs[i]) {
+					rt.Abortf(exitcode.ErrIllegalState, "miscomputed UnsealedCID")
+				}
+			} else {
+				// old precommit, no check needed, checked at precommit
+			}
+		}
+	}
 	svis := make([]proof.AggregateSealVerifyInfo, 0)
 	receiver := rt.Receiver()
 	minerActorID, err := addr.IDFromAddress(receiver)
@@ -1032,6 +1078,7 @@ func (a Actor) ProveCommitSector(rt Runtime, params *ProveCommitSectorParams) *a
 		DealIDs:             precommit.Info.DealIDs,
 		SectorNumber:        precommit.Info.SectorNumber,
 		RegisteredSealProof: precommit.Info.SealProof,
+		UnsealedCID:         precommit.Info.UnsealedCID,
 	})
 
 	code := rt.Send(
@@ -1085,30 +1132,41 @@ func confirmSectorProofsValid(rt Runtime, preCommits []*SectorPreCommitOnChainIn
 
 	activation := rt.CurrEpoch()
 	// Pre-commits for new sectors.
+
+	var sectorsToActivate []market.ActivateDealsParamsInner
+	var preCommitsToActivate []*SectorPreCommitOnChainInfo
+
 	var validPreCommits []*SectorPreCommitOnChainInfo
 	for _, precommit := range preCommits {
 		if len(precommit.Info.DealIDs) > 0 {
-			// Check (and activate) storage deals associated to sector. Abort if checks failed.
-			// TODO: we should batch these calls...
-			// https://github.com/filecoin-project/specs-actors/issues/474
-			code := rt.Send(
-				builtin.StorageMarketActorAddr,
-				builtin.MethodsMarket.ActivateDeals,
-				&market.ActivateDealsParams{
-					DealIDs:      precommit.Info.DealIDs,
-					SectorExpiry: precommit.Info.Expiration,
-				},
-				abi.NewTokenAmount(0),
-				&builtin.Discard{},
-			)
-
-			if code != exitcode.Ok {
-				rt.Log(rtt.INFO, "failed to activate deals on sector %d, dropping from prove commit set", precommit.Info.SectorNumber)
-				continue
-			}
+			sectorsToActivate = append(sectorsToActivate, market.ActivateDealsParamsInner{
+				DealIDs:      precommit.Info.DealIDs,
+				SectorExpiry: precommit.Info.Expiration,
+			})
+			preCommitsToActivate = append(preCommitsToActivate, precommit)
+		} else {
+			validPreCommits = append(validPreCommits, precommit)
 		}
+	}
+	var activateRes market.ActivateDealsReturn
+	code := rt.Send(
+		builtin.StorageMarketActorAddr,
+		builtin.MethodsMarket.ActivateDeals,
+		&market.ActivateDealsParams{
+			Sectors: sectorsToActivate,
+		},
+		abi.NewTokenAmount(0),
+		&activateRes,
+	)
+	builtin.RequireSuccess(rt, code, "failed batch deal activation")
 
-		validPreCommits = append(validPreCommits, precommit)
+	sectorWeights := make(map[abi.SectorNumber]market.ActivateDealsReturnInner)
+	for i, weight := range activateRes.Sectors {
+		if !weight.Success {
+			continue
+		}
+		sectorWeights[preCommitsToActivate[i].Info.SectorNumber] = weight
+		validPreCommits = append(validPreCommits, preCommitsToActivate[i])
 	}
 
 	// When all prove commits have failed abort early
@@ -1134,7 +1192,15 @@ func confirmSectorProofsValid(rt Runtime, preCommits []*SectorPreCommitOnChainIn
 				rt.Log(rtt.WARN, "precommit %d has lifetime %d less than minimum. ignoring", precommit.Info.SectorNumber, duration, MinSectorExpiration)
 				continue
 			}
-			pwr := QAPowerForWeight(info.SectorSize, duration, precommit.DealWeight, precommit.VerifiedDealWeight)
+
+			dealWeight := big.Zero()
+			verifiedDealWeight := big.Zero()
+			if weight, ok := sectorWeights[precommit.Info.SectorNumber]; ok {
+				dealWeight = weight.DealWeight
+				verifiedDealWeight = weight.VerifiedDealWeight
+			}
+
+			pwr := QAPowerForWeight(info.SectorSize, duration, dealWeight, verifiedDealWeight)
 
 			dayReward := ExpectedRewardForPower(thisEpochRewardSmoothed, qualityAdjPowerSmoothed, pwr, builtin.EpochsInDay)
 			// The storage pledge is recorded for use in computing the penalty if this sector is terminated
@@ -1151,8 +1217,8 @@ func confirmSectorProofsValid(rt Runtime, preCommits []*SectorPreCommitOnChainIn
 				DealIDs:               precommit.Info.DealIDs,
 				Expiration:            precommit.Info.Expiration,
 				Activation:            activation,
-				DealWeight:            precommit.DealWeight,
-				VerifiedDealWeight:    precommit.VerifiedDealWeight,
+				DealWeight:            dealWeight,
+				VerifiedDealWeight:    verifiedDealWeight,
 				InitialPledge:         initialPledge,
 				ExpectedDayReward:     dayReward,
 				ExpectedStoragePledge: storagePledge,
@@ -2169,18 +2235,21 @@ func (a Actor) ProveReplicaUpdates(rt Runtime, params *ProveReplicaUpdatesParams
 			continue
 		}
 
+		var activateRes market.ActivateDealsReturn
 		code := rt.Send(
 			builtin.StorageMarketActorAddr,
 			builtin.MethodsMarket.ActivateDeals,
 			&market.ActivateDealsParams{
-				DealIDs:      update.Deals,
-				SectorExpiry: sectorInfo.Expiration,
+				Sectors: []market.ActivateDealsParamsInner{{
+					DealIDs:      update.Deals,
+					SectorExpiry: sectorInfo.Expiration,
+				}},
 			},
 			abi.NewTokenAmount(0),
-			&builtin.Discard{},
+			&activateRes,
 		)
 
-		if code != exitcode.Ok {
+		if code != exitcode.Ok || !activateRes.Sectors[0].Success {
 			rt.Log(rtt.INFO, "failed to activate deals, skipping sector %d", update.SectorID)
 			continue
 		}
@@ -2751,6 +2820,7 @@ type SealVerifyStuff struct {
 	DealIDs []abi.DealID
 	abi.SectorNumber
 	SealRandEpoch abi.ChainEpoch // Used to tie the seal to a chain.
+	UnsealedCID   *cid.Cid
 }
 
 func getVerifyInfo(rt Runtime, params *SealVerifyStuff) *proof.SealVerifyInfo {
@@ -2758,10 +2828,21 @@ func getVerifyInfo(rt Runtime, params *SealVerifyStuff) *proof.SealVerifyInfo {
 		rt.Abortf(exitcode.ErrForbidden, "too early to prove sector")
 	}
 
-	commDs := requestUnsealedSectorCIDs(rt, &market.SectorDataSpec{
+	commD := requestUnsealedSectorCIDs(rt, &market.SectorDataSpec{
 		SectorType: params.RegisteredSealProof,
 		DealIDs:    params.DealIDs,
-	})
+	})[0]
+
+	if len(params.DealIDs) > 0 {
+		if params.UnsealedCID != nil {
+			// new precommit
+			if !params.UnsealedCID.Equals(commD) {
+				rt.Abortf(exitcode.ErrIllegalState, "miscomputed UnsealedCID")
+			}
+		} else {
+			// old precommit, no check needed, checked at precommit
+		}
+	}
 
 	minerActorID, err := addr.IDFromAddress(rt.Receiver())
 	builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "runtime provided non-ID receiver address %v", rt.Receiver())
@@ -2785,7 +2866,7 @@ func getVerifyInfo(rt Runtime, params *SealVerifyStuff) *proof.SealVerifyInfo {
 		Proof:                 params.Proof,
 		Randomness:            abi.SealRandomness(svInfoRandomness),
 		SealedCID:             params.SealedCID,
-		UnsealedCID:           commDs[0],
+		UnsealedCID:           commD,
 	}
 }
 
@@ -2813,6 +2894,25 @@ func requestUnsealedSectorCIDs(rt Runtime, dataCommitmentInputs ...*market.Secto
 	return unsealedCIDs
 }
 
+func verifyDealsForActivation(rt Runtime, sectors []market.SectorDeals) {
+	var dealWeights market.VerifyDealsForActivationReturn
+	code := rt.Send(
+		builtin.StorageMarketActorAddr,
+		builtin.MethodsMarket.VerifyDealsForActivation,
+		&market.VerifyDealsForActivationParams{
+			Sectors: sectors,
+		},
+		abi.NewTokenAmount(0),
+		&dealWeights,
+	)
+	builtin.RequireSuccess(rt, code, "failed to verify deals and get deal weight")
+	if len(dealWeights.Sectors) != len(sectors) {
+		rt.Abortf(exitcode.ErrIllegalState, "deal weight request returned %d records, expected %d",
+			len(dealWeights.Sectors), len(sectors))
+	}
+}
+
+// TODO remove??
 func requestDealWeights(rt Runtime, sectors []market.SectorDeals) *market.VerifyDealsForActivationReturn {
 	// Short-circuit if there are no deals in any of the sectors.
 	dealCount := 0
@@ -2844,6 +2944,10 @@ func requestDealWeights(rt Runtime, sectors []market.SectorDeals) *market.Verify
 		&dealWeights,
 	)
 	builtin.RequireSuccess(rt, code, "failed to verify deals and get deal weight")
+	if len(dealWeights.Sectors) != len(sectors) {
+		rt.Abortf(exitcode.ErrIllegalState, "deal weight request returned %d records, expected %d",
+			len(dealWeights.Sectors), len(sectors))
+	}
 	return &dealWeights
 }
 
diff --git a/actors/builtin/miner/miner_commitment_test.go b/actors/builtin/miner/miner_commitment_test.go
index 00b15c062..dcc29b30a 100644
--- a/actors/builtin/miner/miner_commitment_test.go
+++ b/actors/builtin/miner/miner_commitment_test.go
@@ -91,8 +91,6 @@ func TestCommitments(t *testing.T) {
 
 			// Check precommit expectations.
 			assert.Equal(t, precommitEpoch, precommit.PreCommitEpoch)
-			assert.Equal(t, dealWeight, precommit.DealWeight)
-			assert.Equal(t, verifiedDealWeight, precommit.VerifiedDealWeight)
 
 			assert.Equal(t, test.sectorNo, precommit.Info.SectorNumber)
 			assert.Equal(t, precommitParams.SealProof, precommit.Info.SealProof)
@@ -101,7 +99,7 @@ func TestCommitments(t *testing.T) {
 			assert.Equal(t, precommitParams.DealIDs, precommit.Info.DealIDs)
 			assert.Equal(t, precommitParams.Expiration, precommit.Info.Expiration)
 
-			pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-precommitEpoch, dealWeight, verifiedDealWeight)
+			pwrEstimate := miner.QAPowerMax(actor.sectorSize)
 			expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate)
 			assert.Equal(t, expectedDeposit, precommit.PreCommitDeposit)
 
@@ -135,6 +133,7 @@ func TestCommitments(t *testing.T) {
 	})
 
 	t.Run("deal space exceeds sector space", func(t *testing.T) {
+		t.Skip("TODO needs to be moved to ProveCommit") //TODO
 		actor := newHarness(t, periodOffset)
 		rt := builderForHarness(actor).
 			WithBalance(bigBalance, big.Zero()).
@@ -546,7 +545,7 @@ func TestPreCommitBatch(t *testing.T) {
 					DealWeight:         dealWeight,
 					VerifiedDealWeight: verifiedDealWeight,
 				}
-				pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, sectors[i].Expiration-precommitEpoch, dealWeight, verifiedDealWeight)
+				pwrEstimate := miner.QAPowerMax(actor.sectorSize)
 				deposits[i] = miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate)
 
 			}
@@ -573,8 +572,6 @@ func TestPreCommitBatch(t *testing.T) {
 			st := getState(rt)
 			for i := 0; i < batchSize; i++ {
 				assert.Equal(t, precommitEpoch, precommits[i].PreCommitEpoch)
-				assert.Equal(t, conf.sectorWeights[i].DealWeight, precommits[i].DealWeight)
-				assert.Equal(t, conf.sectorWeights[i].VerifiedDealWeight, precommits[i].VerifiedDealWeight)
 
 				assert.Equal(t, sectorNos[i], precommits[i].Info.SectorNumber)
 				assert.Equal(t, sectors[i].SealProof, precommits[i].Info.SealProof)
@@ -583,8 +580,7 @@ func TestPreCommitBatch(t *testing.T) {
 				assert.Equal(t, sectors[i].DealIDs, precommits[i].Info.DealIDs)
 				assert.Equal(t, sectors[i].Expiration, precommits[i].Info.Expiration)
 
-				pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, precommits[i].Info.Expiration-precommitEpoch,
-					conf.sectorWeights[i].DealWeight, conf.sectorWeights[i].VerifiedDealWeight)
+				pwrEstimate := miner.QAPowerMax(actor.sectorSize)
 				expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate)
 				assert.Equal(t, expectedDeposit, precommits[i].PreCommitDeposit)
 			}
@@ -676,12 +672,7 @@ func TestProveCommit(t *testing.T) {
 		}, true)
 
 		// Check precommit
-		// deal weights must be set in precommit onchain info
-		assert.Equal(t, dealWeight, precommit.DealWeight)
-		assert.Equal(t, verifiedDealWeight, precommit.VerifiedDealWeight)
-
-		pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-precommitEpoch, precommit.DealWeight, precommit.VerifiedDealWeight)
-		expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate)
+		expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize))
 		assert.Equal(t, expectedDeposit, precommit.PreCommitDeposit)
 
 		// expect total precommit deposit to equal our new deposit
@@ -698,8 +689,6 @@ func TestProveCommit(t *testing.T) {
 		assert.Equal(t, precommit.Info.DealIDs, sector.DealIDs)
 		assert.Equal(t, rt.Epoch(), sector.Activation)
 		assert.Equal(t, precommit.Info.Expiration, sector.Expiration)
-		assert.Equal(t, precommit.DealWeight, sector.DealWeight)
-		assert.Equal(t, precommit.VerifiedDealWeight, sector.VerifiedDealWeight)
 
 		// expect precommit to have been removed
 		st = getState(rt)
@@ -712,14 +701,10 @@ func TestProveCommit(t *testing.T) {
 
 		// The sector is exactly full with verified deals, so expect fully verified power.
 		expectedPower := big.Mul(big.NewInt(int64(actor.sectorSize)), big.Div(builtin.VerifiedDealWeightMultiplier, builtin.QualityBaseMultiplier))
-		qaPower := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-rt.Epoch(), precommit.DealWeight, precommit.VerifiedDealWeight)
+		qaPower := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-rt.Epoch(), sector.DealWeight, sector.VerifiedDealWeight)
 		assert.Equal(t, expectedPower, qaPower)
 		sectorPower := miner.NewPowerPair(big.NewIntUnsigned(uint64(actor.sectorSize)), qaPower)
 
-		// expect deal weights to be transferred to on chain info
-		assert.Equal(t, precommit.DealWeight, sector.DealWeight)
-		assert.Equal(t, precommit.VerifiedDealWeight, sector.VerifiedDealWeight)
-
 		// expect initial plege of sector to be set, and be total pledge requirement
 		expectedInitialPledge := miner.InitialPledgeForPower(qaPower, actor.baselinePower, actor.epochRewardSmooth, actor.epochQAPowerSmooth, rt.TotalFilCircSupply())
 		assert.Equal(t, expectedInitialPledge, sector.InitialPledge)
@@ -783,14 +768,10 @@ func TestProveCommit(t *testing.T) {
 		dealLifespan := sectorExpiration - proveCommitEpoch
 		verifiedDealWeight := big.Mul(big.NewIntUnsigned(dealSpace), big.NewInt(int64(dealLifespan)))
 
-		// Power estimates made a pre-commit time
-		noDealPowerEstimate := miner.QAPowerForWeight(actor.sectorSize, sectorExpiration-precommitEpoch, big.Zero(), big.Zero())
-		fullDealPowerEstimate := miner.QAPowerForWeight(actor.sectorSize, sectorExpiration-precommitEpoch, dealWeight, verifiedDealWeight)
-
 		deposits := []big.Int{
-			miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, noDealPowerEstimate),
-			miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, fullDealPowerEstimate),
-			miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, fullDealPowerEstimate),
+			miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize)),
+			miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize)),
+			miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize)),
 		}
 		conf := preCommitBatchConf{
 			sectorWeights: []market.SectorWeights{
@@ -1422,7 +1403,7 @@ func TestBatchMethodNetworkFees(t *testing.T) {
 
 		// Give miner enough balance to pay both and pcd
 		balance := big.Mul(big.NewInt(2), netFee)
-		oneSectorPowerEstimate := miner.QAPowerForWeight(actor.sectorSize, expiration-precommitEpoch, big.Zero(), big.Zero())
+		oneSectorPowerEstimate := miner.QAPowerMax(actor.sectorSize)
 		expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, big.Mul(big.NewInt(4), oneSectorPowerEstimate))
 		balance = big.Add(balance, expectedDeposit)
 		rt.SetBalance(balance)
diff --git a/actors/builtin/miner/miner_state.go b/actors/builtin/miner/miner_state.go
index ff20ef3d9..652d2e91f 100644
--- a/actors/builtin/miner/miner_state.go
+++ b/actors/builtin/miner/miner_state.go
@@ -133,28 +133,29 @@ type WorkerKeyChange struct {
 	EffectiveAt abi.ChainEpoch
 }
 
+// possible states
+// (DealIDs > 0, UnsealedCID != nil) => CommD provided by SP, needs to be checked
+// (DealIDs > 0, UnsealedCID == nil) => Old method or migration, DealIDs checked at PreCommit (Depracated)
+// (DealIDs == 0, UnsealedCID == nil) => NoDeals, CommD of empty sector
+// (DealIDs == 0, UnsealedCID != 0) future approach, fail for now
 // Information provided by a miner when pre-committing a sector.
 type SectorPreCommitInfo struct {
-	SealProof       abi.RegisteredSealProof
-	SectorNumber    abi.SectorNumber
-	SealedCID       cid.Cid `checked:"true"` // CommR
-	SealRandEpoch   abi.ChainEpoch
-	DealIDs         []abi.DealID
-	Expiration      abi.ChainEpoch
-	ReplaceCapacity bool // Whether to replace a "committed capacity" no-deal sector (requires non-empty DealIDs)
-	// The committed capacity sector to replace, and it's deadline/partition location
-	ReplaceSectorDeadline  uint64
-	ReplaceSectorPartition uint64
-	ReplaceSectorNumber    abi.SectorNumber
+	SealProof     abi.RegisteredSealProof
+	SectorNumber  abi.SectorNumber
+	SealedCID     cid.Cid `checked:"true"` // CommR
+	SealRandEpoch abi.ChainEpoch
+	DealIDs       []abi.DealID
+	Expiration    abi.ChainEpoch
+	UnsealedCID   *cid.Cid `checked:"true"`
 }
 
 // Information stored on-chain for a pre-committed sector.
 type SectorPreCommitOnChainInfo struct {
-	Info               SectorPreCommitInfo
-	PreCommitDeposit   abi.TokenAmount
-	PreCommitEpoch     abi.ChainEpoch
-	DealWeight         abi.DealWeight // Integral of active deals over sector lifetime
-	VerifiedDealWeight abi.DealWeight // Integral of active verified deals over sector lifetime
+	Info             SectorPreCommitInfo
+	PreCommitDeposit abi.TokenAmount
+	PreCommitEpoch   abi.ChainEpoch
+	//DealWeight         abi.DealWeight // Integral of active deals over sector lifetime
+	//VerifiedDealWeight abi.DealWeight // Integral of active verified deals over sector lifetime
 }
 
 // Information stored on-chain for a proven sector.
diff --git a/actors/builtin/miner/miner_state_test.go b/actors/builtin/miner/miner_state_test.go
index 2407e3f1e..8bdedff88 100644
--- a/actors/builtin/miner/miner_state_test.go
+++ b/actors/builtin/miner/miner_state_test.go
@@ -1008,11 +1008,9 @@ func constructStateHarness(t *testing.T, periodBoundary abi.ChainEpoch) *stateHa
 func newPreCommitOnChain(sectorNo abi.SectorNumber, sealed cid.Cid, deposit abi.TokenAmount, epoch abi.ChainEpoch) *miner.SectorPreCommitOnChainInfo {
 	info := newSectorPreCommitInfo(sectorNo, sealed)
 	return &miner.SectorPreCommitOnChainInfo{
-		Info:               *info,
-		PreCommitDeposit:   deposit,
-		PreCommitEpoch:     epoch,
-		DealWeight:         big.Zero(),
-		VerifiedDealWeight: big.Zero(),
+		Info:             *info,
+		PreCommitDeposit: deposit,
+		PreCommitEpoch:   epoch,
 	}
 }
 
diff --git a/actors/builtin/miner/miner_test.go b/actors/builtin/miner/miner_test.go
index 6af3a4d90..c0abef82f 100644
--- a/actors/builtin/miner/miner_test.go
+++ b/actors/builtin/miner/miner_test.go
@@ -4166,9 +4166,10 @@ func (h *actorHarness) confirmSectorProofsValidInternal(rt *mock.Runtime, conf p
 		validPrecommits = append(validPrecommits, precommit)
 		if len(precommit.Info.DealIDs) > 0 {
 			vdParams := market.ActivateDealsParams{
-				DealIDs:      precommit.Info.DealIDs,
-				SectorExpiry: precommit.Info.Expiration,
-			}
+				Sectors: []market.ActivateDealsParamsInner{{
+					DealIDs:      precommit.Info.DealIDs,
+					SectorExpiry: precommit.Info.Expiration,
+				}}}
 			exit, found := conf.verifyDealsExit[precommit.Info.SectorNumber]
 			if found {
 				validPrecommits = validPrecommits[:len(validPrecommits)-1] // pop
@@ -4187,21 +4188,18 @@ func (h *actorHarness) confirmSectorProofsValidInternal(rt *mock.Runtime, conf p
 		expectRawPower := big.Zero()
 		for _, precommit := range validPrecommits {
 			precommitOnChain := h.getPreCommit(rt, precommit.Info.SectorNumber)
+			_ = precommitOnChain
 
 			duration := precommit.Info.Expiration - rt.Epoch()
 			if duration >= miner.MinSectorExpiration {
-				qaPowerDelta := miner.QAPowerForWeight(h.sectorSize, duration, precommitOnChain.DealWeight, precommitOnChain.VerifiedDealWeight)
+				//qaPowerDelta := miner.QAPowerForWeight(h.sectorSize, duration, precommitOnChain.DealWeight, precommitOnChain.VerifiedDealWeight)
+				// TODO DealWeight access during prove commit
+				qaPowerDelta := big.Zero()
 				expectQAPower = big.Add(expectQAPower, qaPowerDelta)
 				expectRawPower = big.Add(expectRawPower, big.NewIntUnsigned(uint64(h.sectorSize)))
 				pledge := miner.InitialPledgeForPower(qaPowerDelta, h.baselinePower, h.epochRewardSmooth,
 					h.epochQAPowerSmooth, rt.TotalFilCircSupply())
 
-				// if cc upgrade, pledge is max of new and replaced pledges
-				if precommitOnChain.Info.ReplaceCapacity {
-					replaced := h.getSector(rt, precommitOnChain.Info.ReplaceSectorNumber)
-					pledge = big.Max(pledge, replaced.InitialPledge)
-				}
-
 				expectPledge = big.Add(expectPledge, pledge)
 			}
 		}
diff --git a/actors/builtin/miner/monies.go b/actors/builtin/miner/monies.go
index 8a2d58c76..0db2c0e03 100644
--- a/actors/builtin/miner/monies.go
+++ b/actors/builtin/miner/monies.go
@@ -4,7 +4,6 @@ import (
 	"github.com/filecoin-project/go-state-types/abi"
 	"github.com/filecoin-project/go-state-types/big"
 	"github.com/filecoin-project/go-state-types/exitcode"
-	rtt "github.com/filecoin-project/go-state-types/rt"
 
 	"github.com/filecoin-project/specs-actors/v7/actors/builtin"
 	"github.com/filecoin-project/specs-actors/v7/actors/util/math"
@@ -192,7 +191,6 @@ func RepayDebtsOrAbort(rt Runtime, st *State) abi.TokenAmount {
 	currBalance := rt.CurrentBalance()
 	toBurn, err := st.repayDebts(currBalance)
 	builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "unlocked balance can not repay fee debt")
-	rt.Log(rtt.DEBUG, "RepayDebtsOrAbort was called and succeeded")
 	return toBurn
 }
 
diff --git a/actors/builtin/miner/policy.go b/actors/builtin/miner/policy.go
index e3759d30e..26fc0e54d 100644
--- a/actors/builtin/miner/policy.go
+++ b/actors/builtin/miner/policy.go
@@ -249,6 +249,13 @@ func QualityForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight,
 	return big.Div(big.Div(scaledUpWeightedSumSpaceTime, sectorSpaceTime), builtin.QualityBaseMultiplier)
 }
 
+func QAPowerMax(size abi.SectorSize) abi.StoragePower {
+	// return (size * VerifiedDealWeightMultiplier) / QualityBaseMultiplier
+	// order of operation to preserve maximum precision
+	// for efficiency we could change definition of VerifiedDealWeightMultiplier to be more efficient
+	return big.Div(big.Mul(big.NewIntUnsigned(uint64(size)), builtin.VerifiedDealWeightMultiplier), builtin.QualityBaseMultiplier)
+}
+
 // The power for a sector size, committed duration, and weight.
 func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower {
 	quality := QualityForWeight(size, duration, dealWeight, verifiedWeight)
diff --git a/actors/test/commit_post_test.go b/actors/test/commit_post_test.go
index 90e1185db..1917a8a6f 100644
--- a/actors/test/commit_post_test.go
+++ b/actors/test/commit_post_test.go
@@ -282,7 +282,7 @@ func TestMeasurePreCommitGas(t *testing.T) {
 	require.NoError(t, err)
 	addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), builtin.TokenPrecision), 93837778)
 	owner, worker := addrs[0], addrs[0]
-	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL))
+	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL))
 
 	// Advance vm so we can have seal randomness epoch in the past
 	v, err = v.WithEpoch(abi.ChainEpoch(200))
@@ -327,9 +327,9 @@ func TestMeasurePoRepGas(t *testing.T) {
 	wPoStProof, err := sealProof.RegisteredWindowPoStProof()
 	require.NoError(t, err)
 
-	addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(10_000), builtin.TokenPrecision), 93837778)
+	addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), builtin.TokenPrecision), 93837778)
 	owner, worker := addrs[0], addrs[0]
-	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL))
+	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL))
 
 	// advance vm so we can have seal randomness epoch in the past
 	v, err = v.WithEpoch(abi.ChainEpoch(200))
@@ -620,14 +620,14 @@ func TestAggregateSizeLimits(t *testing.T) {
 	ctx := context.Background()
 	blkStore := ipld.NewBlockStoreInMemory()
 	v := vm.NewVMWithSingletons(ctx, t, blkStore)
-	addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(10_000), big.NewInt(1e18)), 93837778)
+	addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), big.NewInt(1e18)), 93837778)
 
 	// create miner
 	sealProof := abi.RegisteredSealProof_StackedDrg32GiBV1_1
 	wPoStProof, err := sealProof.RegisteredWindowPoStProof()
 	require.NoError(t, err)
 	owner, worker := addrs[0], addrs[0]
-	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL))
+	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL))
 
 	// advance vm so we can have seal randomness epoch in the past
 	v, err = v.WithEpoch(abi.ChainEpoch(200))
@@ -780,9 +780,9 @@ func TestMeasureAggregatePorepGas(t *testing.T) {
 	sealProof := abi.RegisteredSealProof_StackedDrg32GiBV1_1
 	wPoStProof, err := sealProof.RegisteredWindowPoStProof()
 	require.NoError(t, err)
-	addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(10_000), builtin.TokenPrecision), 93837778)
+	addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), builtin.TokenPrecision), 93837778)
 	owner, worker := addrs[0], addrs[0]
-	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL))
+	minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL))
 
 	// advance vm so we can have seal randomness epoch in the past
 	v, err = v.WithEpoch(abi.ChainEpoch(200))
diff --git a/gen/gen.go b/gen/gen.go
index d11535e91..472ebc715 100644
--- a/gen/gen.go
+++ b/gen/gen.go
@@ -119,7 +119,7 @@ func main() {
 		// method params and returns
 		//paych.ConstructorParams{}, // Aliased from v0
 		paych.UpdateChannelStateParams{}, // Changed in v7
-		paych.SignedVoucher{}, // Changed in v7
+		paych.SignedVoucher{},            // Changed in v7
 		//paych.ModVerifyParams{}, // Aliased from v0
 		// other types
 		//paych.Merge{}, // Aliased from v0
@@ -152,7 +152,10 @@ func main() {
 		//market.WithdrawBalanceParams{}, // Aliased from v0
 		// market.PublishStorageDealsParams{}, // Aliased from v0
 		//market.PublishStorageDealsReturn{}, // Aliased from v6
-		//market.ActivateDealsParams{}, // Aliased from v0
+		market.ActivateDealsParams{},
+		market.ActivateDealsParamsInner{},
+		market.ActivateDealsReturn{},
+		market.ActivateDealsReturnInner{},
 		//market.VerifyDealsForActivationParams{}, // Aliased from v3
 		//market.VerifyDealsForActivationReturn{}, // Aliased from v3
 		//market.ComputeDataCommitmentParams{}, // Aliased from v5
@@ -230,9 +233,9 @@ func main() {
 		verifreg.RemoveDataCapParams{}, // New in v7
 		verifreg.RemoveDataCapReturn{}, // New in v7
 		// other types
-		verifreg.RemoveDataCapRequest{}, // New in v7
+		verifreg.RemoveDataCapRequest{},  // New in v7
 		verifreg.RemoveDataCapProposal{}, // New in v7
-		verifreg.RmDcProposalID{}, // New in v7
+		verifreg.RmDcProposalID{},        // New in v7
 	); err != nil {
 		panic(err)
 	}
diff --git a/support/agent/cases_test.go b/support/agent/cases_test.go
index 39d114980..05630ca36 100644
--- a/support/agent/cases_test.go
+++ b/support/agent/cases_test.go
@@ -23,7 +23,7 @@ import (
 
 func TestCreate20Miners(t *testing.T) {
 	ctx := context.Background()
-	initialBalance := big.Mul(big.NewInt(1000), big.NewInt(1e18))
+	initialBalance := big.Mul(big.NewInt(10000), big.NewInt(1e18))
 	minerCount := 20
 
 	rnd := rand.New(rand.NewSource(42))